go.mod: Bump go-winio to v0.6.0
Some minor improvements, but biggest for here is ErrPipeListenerClosed is no longer an errors.New where the string matches the text of the now exported net.ErrClosed in the stdlib, but is just assigned to net.ErrClosed directly. This should allow us to get rid of the string check for "use of closed network connection" here now.. Signed-off-by: Daniel Canter <dcanter@microsoft.com>
This commit is contained in:
parent
4bd8b5be44
commit
acb2964d65
7
go.mod
7
go.mod
@ -5,7 +5,7 @@ go 1.18
|
|||||||
require (
|
require (
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20220903154154-e8044f6e4c72
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20220903154154-e8044f6e4c72
|
||||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b
|
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b
|
||||||
github.com/Microsoft/go-winio v0.5.2
|
github.com/Microsoft/go-winio v0.6.0
|
||||||
github.com/Microsoft/hcsshim v0.10.0-rc.1
|
github.com/Microsoft/hcsshim v0.10.0-rc.1
|
||||||
github.com/container-orchestrated-devices/container-device-interface v0.5.1
|
github.com/container-orchestrated-devices/container-device-interface v0.5.1
|
||||||
github.com/containerd/aufs v1.0.0
|
github.com/containerd/aufs v1.0.0
|
||||||
@ -78,6 +78,11 @@ require (
|
|||||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
|
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||||
|
golang.org/x/tools v0.1.12 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||||
|
8
go.sum
8
go.sum
@ -73,8 +73,8 @@ github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JP
|
|||||||
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
|
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
|
||||||
@ -1095,6 +1095,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -1378,6 +1380,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|||||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||||
|
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
@ -23,7 +23,7 @@ require github.com/AdaLogics/go-fuzz-headers v0.0.0-20220903154154-e8044f6e4c72
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b // indirect
|
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b // indirect
|
||||||
github.com/Microsoft/go-winio v0.5.2 // indirect
|
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||||
github.com/cilium/ebpf v0.9.1 // indirect
|
github.com/cilium/ebpf v0.9.1 // indirect
|
||||||
github.com/container-orchestrated-devices/container-device-interface v0.5.1 // indirect
|
github.com/container-orchestrated-devices/container-device-interface v0.5.1 // indirect
|
||||||
@ -60,9 +60,11 @@ require (
|
|||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||||
go.opencensus.io v0.23.0 // indirect
|
go.opencensus.io v0.23.0 // indirect
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||||
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect
|
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
golang.org/x/tools v0.1.12 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect
|
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect
|
||||||
google.golang.org/grpc v1.47.0 // indirect
|
google.golang.org/grpc v1.47.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.0 // indirect
|
google.golang.org/protobuf v1.28.0 // indirect
|
||||||
|
@ -58,8 +58,9 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jB
|
|||||||
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
|
||||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||||
|
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||||
|
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||||
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
||||||
github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
||||||
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||||
@ -685,6 +686,7 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||||
@ -788,6 +790,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -1048,6 +1052,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||||
golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||||
|
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
1
vendor/github.com/Microsoft/go-winio/.gitattributes
generated
vendored
Normal file
1
vendor/github.com/Microsoft/go-winio/.gitattributes
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
* text=auto eol=lf
|
9
vendor/github.com/Microsoft/go-winio/.gitignore
generated
vendored
9
vendor/github.com/Microsoft/go-winio/.gitignore
generated
vendored
@ -1 +1,10 @@
|
|||||||
|
.vscode/
|
||||||
|
|
||||||
*.exe
|
*.exe
|
||||||
|
|
||||||
|
# testing
|
||||||
|
testdata
|
||||||
|
|
||||||
|
# go workspaces
|
||||||
|
go.work
|
||||||
|
go.work.sum
|
||||||
|
144
vendor/github.com/Microsoft/go-winio/.golangci.yml
generated
vendored
Normal file
144
vendor/github.com/Microsoft/go-winio/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
run:
|
||||||
|
skip-dirs:
|
||||||
|
- pkg/etw/sample
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
# style
|
||||||
|
- containedctx # struct contains a context
|
||||||
|
- dupl # duplicate code
|
||||||
|
- errname # erorrs are named correctly
|
||||||
|
- goconst # strings that should be constants
|
||||||
|
- godot # comments end in a period
|
||||||
|
- misspell
|
||||||
|
- nolintlint # "//nolint" directives are properly explained
|
||||||
|
- revive # golint replacement
|
||||||
|
- stylecheck # golint replacement, less configurable than revive
|
||||||
|
- unconvert # unnecessary conversions
|
||||||
|
- wastedassign
|
||||||
|
|
||||||
|
# bugs, performance, unused, etc ...
|
||||||
|
- contextcheck # function uses a non-inherited context
|
||||||
|
- errorlint # errors not wrapped for 1.13
|
||||||
|
- exhaustive # check exhaustiveness of enum switch statements
|
||||||
|
- gofmt # files are gofmt'ed
|
||||||
|
- gosec # security
|
||||||
|
- nestif # deeply nested ifs
|
||||||
|
- nilerr # returns nil even with non-nil error
|
||||||
|
- prealloc # slices that can be pre-allocated
|
||||||
|
- structcheck # unused struct fields
|
||||||
|
- unparam # unused function params
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
# err is very often shadowed in nested scopes
|
||||||
|
- linters:
|
||||||
|
- govet
|
||||||
|
text: '^shadow: declaration of "err" shadows declaration'
|
||||||
|
|
||||||
|
# ignore long lines for skip autogen directives
|
||||||
|
- linters:
|
||||||
|
- revive
|
||||||
|
text: "^line-length-limit: "
|
||||||
|
source: "^//(go:generate|sys) "
|
||||||
|
|
||||||
|
# allow unjustified ignores of error checks in defer statements
|
||||||
|
- linters:
|
||||||
|
- nolintlint
|
||||||
|
text: "^directive `//nolint:errcheck` should provide explanation"
|
||||||
|
source: '^\s*defer '
|
||||||
|
|
||||||
|
# allow unjustified ignores of error lints for io.EOF
|
||||||
|
- linters:
|
||||||
|
- nolintlint
|
||||||
|
text: "^directive `//nolint:errorlint` should provide explanation"
|
||||||
|
source: '[=|!]= io.EOF'
|
||||||
|
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
govet:
|
||||||
|
enable-all: true
|
||||||
|
disable:
|
||||||
|
# struct order is often for Win32 compat
|
||||||
|
# also, ignore pointer bytes/GC issues for now until performance becomes an issue
|
||||||
|
- fieldalignment
|
||||||
|
check-shadowing: true
|
||||||
|
nolintlint:
|
||||||
|
allow-leading-space: false
|
||||||
|
require-explanation: true
|
||||||
|
require-specific: true
|
||||||
|
revive:
|
||||||
|
# revive is more configurable than static check, so likely the preferred alternative to static-check
|
||||||
|
# (once the perf issue is solved: https://github.com/golangci/golangci-lint/issues/2997)
|
||||||
|
enable-all-rules:
|
||||||
|
true
|
||||||
|
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md
|
||||||
|
rules:
|
||||||
|
# rules with required arguments
|
||||||
|
- name: argument-limit
|
||||||
|
disabled: true
|
||||||
|
- name: banned-characters
|
||||||
|
disabled: true
|
||||||
|
- name: cognitive-complexity
|
||||||
|
disabled: true
|
||||||
|
- name: cyclomatic
|
||||||
|
disabled: true
|
||||||
|
- name: file-header
|
||||||
|
disabled: true
|
||||||
|
- name: function-length
|
||||||
|
disabled: true
|
||||||
|
- name: function-result-limit
|
||||||
|
disabled: true
|
||||||
|
- name: max-public-structs
|
||||||
|
disabled: true
|
||||||
|
# geneally annoying rules
|
||||||
|
- name: add-constant # complains about any and all strings and integers
|
||||||
|
disabled: true
|
||||||
|
- name: confusing-naming # we frequently use "Foo()" and "foo()" together
|
||||||
|
disabled: true
|
||||||
|
- name: flag-parameter # excessive, and a common idiom we use
|
||||||
|
disabled: true
|
||||||
|
# general config
|
||||||
|
- name: line-length-limit
|
||||||
|
arguments:
|
||||||
|
- 140
|
||||||
|
- name: var-naming
|
||||||
|
arguments:
|
||||||
|
- []
|
||||||
|
- - CID
|
||||||
|
- CRI
|
||||||
|
- CTRD
|
||||||
|
- DACL
|
||||||
|
- DLL
|
||||||
|
- DOS
|
||||||
|
- ETW
|
||||||
|
- FSCTL
|
||||||
|
- GCS
|
||||||
|
- GMSA
|
||||||
|
- HCS
|
||||||
|
- HV
|
||||||
|
- IO
|
||||||
|
- LCOW
|
||||||
|
- LDAP
|
||||||
|
- LPAC
|
||||||
|
- LTSC
|
||||||
|
- MMIO
|
||||||
|
- NT
|
||||||
|
- OCI
|
||||||
|
- PMEM
|
||||||
|
- PWSH
|
||||||
|
- RX
|
||||||
|
- SACl
|
||||||
|
- SID
|
||||||
|
- SMB
|
||||||
|
- TX
|
||||||
|
- VHD
|
||||||
|
- VHDX
|
||||||
|
- VMID
|
||||||
|
- VPCI
|
||||||
|
- WCOW
|
||||||
|
- WIM
|
||||||
|
stylecheck:
|
||||||
|
checks:
|
||||||
|
- "all"
|
||||||
|
- "-ST1003" # use revive's var naming
|
74
vendor/github.com/Microsoft/go-winio/README.md
generated
vendored
74
vendor/github.com/Microsoft/go-winio/README.md
generated
vendored
@ -13,16 +13,60 @@ Please see the LICENSE file for licensing information.
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA)
|
This project welcomes contributions and suggestions.
|
||||||
declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
|
Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that
|
||||||
|
you have the right to, and actually do, grant us the rights to use your contribution.
|
||||||
|
For details, visit [Microsoft CLA](https://cla.microsoft.com).
|
||||||
|
|
||||||
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR
|
When you submit a pull request, a CLA-bot will automatically determine whether you need to
|
||||||
appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
|
provide a CLA and decorate the PR appropriately (e.g., label, comment).
|
||||||
|
Simply follow the instructions provided by the bot.
|
||||||
|
You will only need to do this once across all repos using our CLA.
|
||||||
|
|
||||||
We also require that contributors sign their commits using git commit -s or git commit --signoff to certify they either authored the work themselves
|
Additionally, the pull request pipeline requires the following steps to be performed before
|
||||||
or otherwise have permission to use it in this project. Please see https://developercertificate.org/ for more info, as well as to make sure that you can
|
mergining.
|
||||||
attest to the rules listed. Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off.
|
|
||||||
|
|
||||||
|
### Code Sign-Off
|
||||||
|
|
||||||
|
We require that contributors sign their commits using [`git commit --signoff`][git-commit-s]
|
||||||
|
to certify they either authored the work themselves or otherwise have permission to use it in this project.
|
||||||
|
|
||||||
|
A range of commits can be signed off using [`git rebase --signoff`][git-rebase-s].
|
||||||
|
|
||||||
|
Please see [the developer certificate](https://developercertificate.org) for more info,
|
||||||
|
as well as to make sure that you can attest to the rules listed.
|
||||||
|
Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off.
|
||||||
|
|
||||||
|
### Linting
|
||||||
|
|
||||||
|
Code must pass a linting stage, which uses [`golangci-lint`][lint].
|
||||||
|
The linting settings are stored in [`.golangci.yaml`](./.golangci.yaml), and can be run
|
||||||
|
automatically with VSCode by adding the following to your workspace or folder settings:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"go.lintTool": "golangci-lint",
|
||||||
|
"go.lintOnSave": "package",
|
||||||
|
```
|
||||||
|
|
||||||
|
Additional editor [integrations options are also available][lint-ide].
|
||||||
|
|
||||||
|
Alternatively, `golangci-lint` can be [installed locally][lint-install] and run from the repo root:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# use . or specify a path to only lint a package
|
||||||
|
# to show all lint errors, use flags "--max-issues-per-linter=0 --max-same-issues=0"
|
||||||
|
> golangci-lint run ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Go Generate
|
||||||
|
|
||||||
|
The pipeline checks that auto-generated code, via `go generate`, are up to date.
|
||||||
|
|
||||||
|
This can be done for the entire repo:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
> go generate ./...
|
||||||
|
```
|
||||||
|
|
||||||
## Code of Conduct
|
## Code of Conduct
|
||||||
|
|
||||||
@ -30,8 +74,16 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
|||||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Special Thanks
|
## Special Thanks
|
||||||
Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe
|
|
||||||
for another named pipe implementation.
|
Thanks to [natefinch][natefinch] for the inspiration for this library.
|
||||||
|
See [npipe](https://github.com/natefinch/npipe) for another named pipe implementation.
|
||||||
|
|
||||||
|
[lint]: https://golangci-lint.run/
|
||||||
|
[lint-ide]: https://golangci-lint.run/usage/integrations/#editor-integration
|
||||||
|
[lint-install]: https://golangci-lint.run/usage/install/#local-installation
|
||||||
|
|
||||||
|
[git-commit-s]: https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s
|
||||||
|
[git-rebase-s]: https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---signoff
|
||||||
|
|
||||||
|
[natefinch]: https://github.com/natefinch
|
||||||
|
41
vendor/github.com/Microsoft/go-winio/SECURITY.md
generated
vendored
Normal file
41
vendor/github.com/Microsoft/go-winio/SECURITY.md
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||||
|
|
||||||
|
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
|
||||||
|
|
||||||
|
## Reporting Security Issues
|
||||||
|
|
||||||
|
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||||
|
|
||||||
|
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
|
||||||
|
|
||||||
|
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
|
||||||
|
|
||||||
|
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
|
||||||
|
|
||||||
|
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||||
|
|
||||||
|
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||||
|
* Full paths of source file(s) related to the manifestation of the issue
|
||||||
|
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||||
|
* Any special configuration required to reproduce the issue
|
||||||
|
* Step-by-step instructions to reproduce the issue
|
||||||
|
* Proof-of-concept or exploit code (if possible)
|
||||||
|
* Impact of the issue, including how an attacker might exploit the issue
|
||||||
|
|
||||||
|
This information will help us triage your report more quickly.
|
||||||
|
|
||||||
|
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
|
||||||
|
|
||||||
|
## Preferred Languages
|
||||||
|
|
||||||
|
We prefer all communications to be in English.
|
||||||
|
|
||||||
|
## Policy
|
||||||
|
|
||||||
|
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
|
||||||
|
|
||||||
|
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
48
vendor/github.com/Microsoft/go-winio/backup.go
generated
vendored
48
vendor/github.com/Microsoft/go-winio/backup.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package winio
|
package winio
|
||||||
@ -7,11 +8,12 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
|
//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
|
||||||
@ -24,7 +26,7 @@ const (
|
|||||||
BackupAlternateData
|
BackupAlternateData
|
||||||
BackupLink
|
BackupLink
|
||||||
BackupPropertyData
|
BackupPropertyData
|
||||||
BackupObjectId
|
BackupObjectId //revive:disable-line:var-naming ID, not Id
|
||||||
BackupReparseData
|
BackupReparseData
|
||||||
BackupSparseBlock
|
BackupSparseBlock
|
||||||
BackupTxfsData
|
BackupTxfsData
|
||||||
@ -34,14 +36,16 @@ const (
|
|||||||
StreamSparseAttributes = uint32(8)
|
StreamSparseAttributes = uint32(8)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//nolint:revive // var-naming: ALL_CAPS
|
||||||
const (
|
const (
|
||||||
WRITE_DAC = 0x40000
|
WRITE_DAC = windows.WRITE_DAC
|
||||||
WRITE_OWNER = 0x80000
|
WRITE_OWNER = windows.WRITE_OWNER
|
||||||
ACCESS_SYSTEM_SECURITY = 0x1000000
|
ACCESS_SYSTEM_SECURITY = windows.ACCESS_SYSTEM_SECURITY
|
||||||
)
|
)
|
||||||
|
|
||||||
// BackupHeader represents a backup stream of a file.
|
// BackupHeader represents a backup stream of a file.
|
||||||
type BackupHeader struct {
|
type BackupHeader struct {
|
||||||
|
//revive:disable-next-line:var-naming ID, not Id
|
||||||
Id uint32 // The backup stream ID
|
Id uint32 // The backup stream ID
|
||||||
Attributes uint32 // Stream attributes
|
Attributes uint32 // Stream attributes
|
||||||
Size int64 // The size of the stream in bytes
|
Size int64 // The size of the stream in bytes
|
||||||
@ -49,8 +53,8 @@ type BackupHeader struct {
|
|||||||
Offset int64 // The offset of the stream in the file (for BackupSparseBlock only).
|
Offset int64 // The offset of the stream in the file (for BackupSparseBlock only).
|
||||||
}
|
}
|
||||||
|
|
||||||
type win32StreamId struct {
|
type win32StreamID struct {
|
||||||
StreamId uint32
|
StreamID uint32
|
||||||
Attributes uint32
|
Attributes uint32
|
||||||
Size uint64
|
Size uint64
|
||||||
NameSize uint32
|
NameSize uint32
|
||||||
@ -71,7 +75,7 @@ func NewBackupStreamReader(r io.Reader) *BackupStreamReader {
|
|||||||
// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if
|
// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if
|
||||||
// it was not completely read.
|
// it was not completely read.
|
||||||
func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
||||||
if r.bytesLeft > 0 {
|
if r.bytesLeft > 0 { //nolint:nestif // todo: flatten this
|
||||||
if s, ok := r.r.(io.Seeker); ok {
|
if s, ok := r.r.(io.Seeker); ok {
|
||||||
// Make sure Seek on io.SeekCurrent sometimes succeeds
|
// Make sure Seek on io.SeekCurrent sometimes succeeds
|
||||||
// before trying the actual seek.
|
// before trying the actual seek.
|
||||||
@ -82,16 +86,16 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
|||||||
r.bytesLeft = 0
|
r.bytesLeft = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err := io.Copy(ioutil.Discard, r); err != nil {
|
if _, err := io.Copy(io.Discard, r); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var wsi win32StreamId
|
var wsi win32StreamID
|
||||||
if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil {
|
if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hdr := &BackupHeader{
|
hdr := &BackupHeader{
|
||||||
Id: wsi.StreamId,
|
Id: wsi.StreamID,
|
||||||
Attributes: wsi.Attributes,
|
Attributes: wsi.Attributes,
|
||||||
Size: int64(wsi.Size),
|
Size: int64(wsi.Size),
|
||||||
}
|
}
|
||||||
@ -102,7 +106,7 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
|||||||
}
|
}
|
||||||
hdr.Name = syscall.UTF16ToString(name)
|
hdr.Name = syscall.UTF16ToString(name)
|
||||||
}
|
}
|
||||||
if wsi.StreamId == BackupSparseBlock {
|
if wsi.StreamID == BackupSparseBlock {
|
||||||
if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
|
if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -147,8 +151,8 @@ func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error {
|
|||||||
return fmt.Errorf("missing %d bytes", w.bytesLeft)
|
return fmt.Errorf("missing %d bytes", w.bytesLeft)
|
||||||
}
|
}
|
||||||
name := utf16.Encode([]rune(hdr.Name))
|
name := utf16.Encode([]rune(hdr.Name))
|
||||||
wsi := win32StreamId{
|
wsi := win32StreamID{
|
||||||
StreamId: hdr.Id,
|
StreamID: hdr.Id,
|
||||||
Attributes: hdr.Attributes,
|
Attributes: hdr.Attributes,
|
||||||
Size: uint64(hdr.Size),
|
Size: uint64(hdr.Size),
|
||||||
NameSize: uint32(len(name) * 2),
|
NameSize: uint32(len(name) * 2),
|
||||||
@ -203,7 +207,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) {
|
|||||||
var bytesRead uint32
|
var bytesRead uint32
|
||||||
err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
|
err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, &os.PathError{"BackupRead", r.f.Name(), err}
|
return 0, &os.PathError{Op: "BackupRead", Path: r.f.Name(), Err: err}
|
||||||
}
|
}
|
||||||
runtime.KeepAlive(r.f)
|
runtime.KeepAlive(r.f)
|
||||||
if bytesRead == 0 {
|
if bytesRead == 0 {
|
||||||
@ -216,7 +220,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) {
|
|||||||
// the underlying file.
|
// the underlying file.
|
||||||
func (r *BackupFileReader) Close() error {
|
func (r *BackupFileReader) Close() error {
|
||||||
if r.ctx != 0 {
|
if r.ctx != 0 {
|
||||||
backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
|
_ = backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
|
||||||
runtime.KeepAlive(r.f)
|
runtime.KeepAlive(r.f)
|
||||||
r.ctx = 0
|
r.ctx = 0
|
||||||
}
|
}
|
||||||
@ -242,7 +246,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) {
|
|||||||
var bytesWritten uint32
|
var bytesWritten uint32
|
||||||
err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
|
err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, &os.PathError{"BackupWrite", w.f.Name(), err}
|
return 0, &os.PathError{Op: "BackupWrite", Path: w.f.Name(), Err: err}
|
||||||
}
|
}
|
||||||
runtime.KeepAlive(w.f)
|
runtime.KeepAlive(w.f)
|
||||||
if int(bytesWritten) != len(b) {
|
if int(bytesWritten) != len(b) {
|
||||||
@ -255,7 +259,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) {
|
|||||||
// close the underlying file.
|
// close the underlying file.
|
||||||
func (w *BackupFileWriter) Close() error {
|
func (w *BackupFileWriter) Close() error {
|
||||||
if w.ctx != 0 {
|
if w.ctx != 0 {
|
||||||
backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
|
_ = backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
|
||||||
runtime.KeepAlive(w.f)
|
runtime.KeepAlive(w.f)
|
||||||
w.ctx = 0
|
w.ctx = 0
|
||||||
}
|
}
|
||||||
@ -271,7 +275,13 @@ func OpenForBackup(path string, access uint32, share uint32, createmode uint32)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0)
|
h, err := syscall.CreateFile(&winPath[0],
|
||||||
|
access,
|
||||||
|
share,
|
||||||
|
nil,
|
||||||
|
createmode,
|
||||||
|
syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT,
|
||||||
|
0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = &os.PathError{Op: "open", Path: path, Err: err}
|
err = &os.PathError{Op: "open", Path: path, Err: err}
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// +build !windows
|
|
||||||
// This file only exists to allow go get on non-Windows platforms.
|
// This file only exists to allow go get on non-Windows platforms.
|
||||||
|
|
||||||
package backuptar
|
package backuptar
|
2
vendor/github.com/Microsoft/go-winio/backuptar/strconv.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/backuptar/strconv.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
package backuptar
|
package backuptar
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
146
vendor/github.com/Microsoft/go-winio/backuptar/tar.go
generated
vendored
146
vendor/github.com/Microsoft/go-winio/backuptar/tar.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package backuptar
|
package backuptar
|
||||||
@ -7,7 +8,6 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -18,17 +18,18 @@ import (
|
|||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//nolint:deadcode,varcheck // keep unused constants for potential future use
|
||||||
const (
|
const (
|
||||||
c_ISUID = 04000 // Set uid
|
cISUID = 0004000 // Set uid
|
||||||
c_ISGID = 02000 // Set gid
|
cISGID = 0002000 // Set gid
|
||||||
c_ISVTX = 01000 // Save text (sticky bit)
|
cISVTX = 0001000 // Save text (sticky bit)
|
||||||
c_ISDIR = 040000 // Directory
|
cISDIR = 0040000 // Directory
|
||||||
c_ISFIFO = 010000 // FIFO
|
cISFIFO = 0010000 // FIFO
|
||||||
c_ISREG = 0100000 // Regular file
|
cISREG = 0100000 // Regular file
|
||||||
c_ISLNK = 0120000 // Symbolic link
|
cISLNK = 0120000 // Symbolic link
|
||||||
c_ISBLK = 060000 // Block special file
|
cISBLK = 0060000 // Block special file
|
||||||
c_ISCHR = 020000 // Character special file
|
cISCHR = 0020000 // Character special file
|
||||||
c_ISSOCK = 0140000 // Socket
|
cISSOCK = 0140000 // Socket
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -44,7 +45,7 @@ const (
|
|||||||
// zeroReader is an io.Reader that always returns 0s.
|
// zeroReader is an io.Reader that always returns 0s.
|
||||||
type zeroReader struct{}
|
type zeroReader struct{}
|
||||||
|
|
||||||
func (zr zeroReader) Read(b []byte) (int, error) {
|
func (zeroReader) Read(b []byte) (int, error) {
|
||||||
for i := range b {
|
for i := range b {
|
||||||
b[i] = 0
|
b[i] = 0
|
||||||
}
|
}
|
||||||
@ -55,7 +56,7 @@ func copySparse(t *tar.Writer, br *winio.BackupStreamReader) error {
|
|||||||
curOffset := int64(0)
|
curOffset := int64(0)
|
||||||
for {
|
for {
|
||||||
bhdr, err := br.Next()
|
bhdr, err := br.Next()
|
||||||
if err == io.EOF {
|
if err == io.EOF { //nolint:errorlint
|
||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -71,8 +72,8 @@ func copySparse(t *tar.Writer, br *winio.BackupStreamReader) error {
|
|||||||
}
|
}
|
||||||
// archive/tar does not support writing sparse files
|
// archive/tar does not support writing sparse files
|
||||||
// so just write zeroes to catch up to the current offset.
|
// so just write zeroes to catch up to the current offset.
|
||||||
if _, err := io.CopyN(t, zeroReader{}, bhdr.Offset-curOffset); err != nil {
|
if _, err = io.CopyN(t, zeroReader{}, bhdr.Offset-curOffset); err != nil {
|
||||||
return fmt.Errorf("seek to offset %d: %s", bhdr.Offset, err)
|
return fmt.Errorf("seek to offset %d: %w", bhdr.Offset, err)
|
||||||
}
|
}
|
||||||
if bhdr.Size == 0 {
|
if bhdr.Size == 0 {
|
||||||
// A sparse block with size = 0 is used to mark the end of the sparse blocks.
|
// A sparse block with size = 0 is used to mark the end of the sparse blocks.
|
||||||
@ -106,7 +107,7 @@ func BasicInfoHeader(name string, size int64, fileInfo *winio.FileBasicInfo) *ta
|
|||||||
hdr.PAXRecords[hdrCreationTime] = formatPAXTime(time.Unix(0, fileInfo.CreationTime.Nanoseconds()))
|
hdr.PAXRecords[hdrCreationTime] = formatPAXTime(time.Unix(0, fileInfo.CreationTime.Nanoseconds()))
|
||||||
|
|
||||||
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
|
||||||
hdr.Mode |= c_ISDIR
|
hdr.Mode |= cISDIR
|
||||||
hdr.Size = 0
|
hdr.Size = 0
|
||||||
hdr.Typeflag = tar.TypeDir
|
hdr.Typeflag = tar.TypeDir
|
||||||
}
|
}
|
||||||
@ -116,32 +117,29 @@ func BasicInfoHeader(name string, size int64, fileInfo *winio.FileBasicInfo) *ta
|
|||||||
// SecurityDescriptorFromTarHeader reads the SDDL associated with the header of the current file
|
// SecurityDescriptorFromTarHeader reads the SDDL associated with the header of the current file
|
||||||
// from the tar header and returns the security descriptor into a byte slice.
|
// from the tar header and returns the security descriptor into a byte slice.
|
||||||
func SecurityDescriptorFromTarHeader(hdr *tar.Header) ([]byte, error) {
|
func SecurityDescriptorFromTarHeader(hdr *tar.Header) ([]byte, error) {
|
||||||
// Maintaining old SDDL-based behavior for backward
|
|
||||||
// compatibility. All new tar headers written by this library
|
|
||||||
// will have raw binary for the security descriptor.
|
|
||||||
var sd []byte
|
|
||||||
var err error
|
|
||||||
if sddl, ok := hdr.PAXRecords[hdrSecurityDescriptor]; ok {
|
|
||||||
sd, err = winio.SddlToSecurityDescriptor(sddl)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sdraw, ok := hdr.PAXRecords[hdrRawSecurityDescriptor]; ok {
|
if sdraw, ok := hdr.PAXRecords[hdrRawSecurityDescriptor]; ok {
|
||||||
sd, err = base64.StdEncoding.DecodeString(sdraw)
|
sd, err := base64.StdEncoding.DecodeString(sdraw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Not returning sd as-is in the error-case, as base64.DecodeString
|
||||||
|
// may return partially decoded data (not nil or empty slice) in case
|
||||||
|
// of a failure: https://github.com/golang/go/blob/go1.17.7/src/encoding/base64/base64.go#L382-L387
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return sd, nil
|
||||||
}
|
}
|
||||||
return sd, nil
|
// Maintaining old SDDL-based behavior for backward compatibility. All new
|
||||||
|
// tar headers written by this library will have raw binary for the security
|
||||||
|
// descriptor.
|
||||||
|
if sddl, ok := hdr.PAXRecords[hdrSecurityDescriptor]; ok {
|
||||||
|
return winio.SddlToSecurityDescriptor(sddl)
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtendedAttributesFromTarHeader reads the EAs associated with the header of the
|
// ExtendedAttributesFromTarHeader reads the EAs associated with the header of the
|
||||||
// current file from the tar header and returns it as a byte slice.
|
// current file from the tar header and returns it as a byte slice.
|
||||||
func ExtendedAttributesFromTarHeader(hdr *tar.Header) ([]byte, error) {
|
func ExtendedAttributesFromTarHeader(hdr *tar.Header) ([]byte, error) {
|
||||||
var eas []winio.ExtendedAttribute
|
var eas []winio.ExtendedAttribute //nolint:prealloc // len(eas) <= len(hdr.PAXRecords); prealloc is wasteful
|
||||||
var eadata []byte
|
|
||||||
var err error
|
|
||||||
for k, v := range hdr.PAXRecords {
|
for k, v := range hdr.PAXRecords {
|
||||||
if !strings.HasPrefix(k, hdrEaPrefix) {
|
if !strings.HasPrefix(k, hdrEaPrefix) {
|
||||||
continue
|
continue
|
||||||
@ -155,13 +153,15 @@ func ExtendedAttributesFromTarHeader(hdr *tar.Header) ([]byte, error) {
|
|||||||
Value: data,
|
Value: data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
var eaData []byte
|
||||||
|
var err error
|
||||||
if len(eas) != 0 {
|
if len(eas) != 0 {
|
||||||
eadata, err = winio.EncodeExtendedAttributes(eas)
|
eaData, err = winio.EncodeExtendedAttributes(eas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return eadata, nil
|
return eaData, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeReparsePointFromTarHeader reads the ReparsePoint structure from the tar header
|
// EncodeReparsePointFromTarHeader reads the ReparsePoint structure from the tar header
|
||||||
@ -182,11 +182,9 @@ func EncodeReparsePointFromTarHeader(hdr *tar.Header) []byte {
|
|||||||
//
|
//
|
||||||
// The additional Win32 metadata is:
|
// The additional Win32 metadata is:
|
||||||
//
|
//
|
||||||
// MSWINDOWS.fileattr: The Win32 file attributes, as a decimal value
|
// - MSWINDOWS.fileattr: The Win32 file attributes, as a decimal value
|
||||||
//
|
// - MSWINDOWS.rawsd: The Win32 security descriptor, in raw binary format
|
||||||
// MSWINDOWS.rawsd: The Win32 security descriptor, in raw binary format
|
// - MSWINDOWS.mountpoint: If present, this is a mount point and not a symlink, even though the type is '2' (symlink)
|
||||||
//
|
|
||||||
// MSWINDOWS.mountpoint: If present, this is a mount point and not a symlink, even though the type is '2' (symlink)
|
|
||||||
func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size int64, fileInfo *winio.FileBasicInfo) error {
|
func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size int64, fileInfo *winio.FileBasicInfo) error {
|
||||||
name = filepath.ToSlash(name)
|
name = filepath.ToSlash(name)
|
||||||
hdr := BasicInfoHeader(name, size, fileInfo)
|
hdr := BasicInfoHeader(name, size, fileInfo)
|
||||||
@ -209,7 +207,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
|
|||||||
var dataHdr *winio.BackupHeader
|
var dataHdr *winio.BackupHeader
|
||||||
for dataHdr == nil {
|
for dataHdr == nil {
|
||||||
bhdr, err := br.Next()
|
bhdr, err := br.Next()
|
||||||
if err == io.EOF {
|
if err == io.EOF { //nolint:errorlint
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -217,21 +215,21 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
|
|||||||
}
|
}
|
||||||
switch bhdr.Id {
|
switch bhdr.Id {
|
||||||
case winio.BackupData:
|
case winio.BackupData:
|
||||||
hdr.Mode |= c_ISREG
|
hdr.Mode |= cISREG
|
||||||
if !readTwice {
|
if !readTwice {
|
||||||
dataHdr = bhdr
|
dataHdr = bhdr
|
||||||
}
|
}
|
||||||
case winio.BackupSecurity:
|
case winio.BackupSecurity:
|
||||||
sd, err := ioutil.ReadAll(br)
|
sd, err := io.ReadAll(br)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
hdr.PAXRecords[hdrRawSecurityDescriptor] = base64.StdEncoding.EncodeToString(sd)
|
hdr.PAXRecords[hdrRawSecurityDescriptor] = base64.StdEncoding.EncodeToString(sd)
|
||||||
|
|
||||||
case winio.BackupReparseData:
|
case winio.BackupReparseData:
|
||||||
hdr.Mode |= c_ISLNK
|
hdr.Mode |= cISLNK
|
||||||
hdr.Typeflag = tar.TypeSymlink
|
hdr.Typeflag = tar.TypeSymlink
|
||||||
reparseBuffer, err := ioutil.ReadAll(br)
|
reparseBuffer, _ := io.ReadAll(br)
|
||||||
rp, err := winio.DecodeReparsePoint(reparseBuffer)
|
rp, err := winio.DecodeReparsePoint(reparseBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -242,7 +240,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
|
|||||||
hdr.Linkname = rp.Target
|
hdr.Linkname = rp.Target
|
||||||
|
|
||||||
case winio.BackupEaData:
|
case winio.BackupEaData:
|
||||||
eab, err := ioutil.ReadAll(br)
|
eab, err := io.ReadAll(br)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -276,7 +274,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
|
|||||||
}
|
}
|
||||||
for dataHdr == nil {
|
for dataHdr == nil {
|
||||||
bhdr, err := br.Next()
|
bhdr, err := br.Next()
|
||||||
if err == io.EOF {
|
if err == io.EOF { //nolint:errorlint
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -311,7 +309,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
|
|||||||
// range of the file containing the range contents. Finally there is a sparse block stream with
|
// range of the file containing the range contents. Finally there is a sparse block stream with
|
||||||
// size = 0 and offset = <file size>.
|
// size = 0 and offset = <file size>.
|
||||||
|
|
||||||
if dataHdr != nil {
|
if dataHdr != nil { //nolint:nestif // todo: reduce nesting complexity
|
||||||
// A data stream was found. Copy the data.
|
// A data stream was found. Copy the data.
|
||||||
// We assume that we will either have a data stream size > 0 XOR have sparse block streams.
|
// We assume that we will either have a data stream size > 0 XOR have sparse block streams.
|
||||||
if dataHdr.Size > 0 || (dataHdr.Attributes&winio.StreamSparseAttributes) == 0 {
|
if dataHdr.Size > 0 || (dataHdr.Attributes&winio.StreamSparseAttributes) == 0 {
|
||||||
@ -319,13 +317,13 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
|
|||||||
return fmt.Errorf("%s: mismatch between file size %d and header size %d", name, size, dataHdr.Size)
|
return fmt.Errorf("%s: mismatch between file size %d and header size %d", name, size, dataHdr.Size)
|
||||||
}
|
}
|
||||||
if _, err = io.Copy(t, br); err != nil {
|
if _, err = io.Copy(t, br); err != nil {
|
||||||
return fmt.Errorf("%s: copying contents from data stream: %s", name, err)
|
return fmt.Errorf("%s: copying contents from data stream: %w", name, err)
|
||||||
}
|
}
|
||||||
} else if size > 0 {
|
} else if size > 0 {
|
||||||
// As of a recent OS change, BackupRead now returns a data stream for empty sparse files.
|
// As of a recent OS change, BackupRead now returns a data stream for empty sparse files.
|
||||||
// These files have no sparse block streams, so skip the copySparse call if file size = 0.
|
// These files have no sparse block streams, so skip the copySparse call if file size = 0.
|
||||||
if err = copySparse(t, br); err != nil {
|
if err = copySparse(t, br); err != nil {
|
||||||
return fmt.Errorf("%s: copying contents from sparse block stream: %s", name, err)
|
return fmt.Errorf("%s: copying contents from sparse block stream: %w", name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -335,7 +333,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
|
|||||||
// been written. In practice, this means that we don't get EA or TXF metadata.
|
// been written. In practice, this means that we don't get EA or TXF metadata.
|
||||||
for {
|
for {
|
||||||
bhdr, err := br.Next()
|
bhdr, err := br.Next()
|
||||||
if err == io.EOF {
|
if err == io.EOF { //nolint:errorlint
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -343,35 +341,30 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
|
|||||||
}
|
}
|
||||||
switch bhdr.Id {
|
switch bhdr.Id {
|
||||||
case winio.BackupAlternateData:
|
case winio.BackupAlternateData:
|
||||||
altName := bhdr.Name
|
if (bhdr.Attributes & winio.StreamSparseAttributes) != 0 {
|
||||||
if strings.HasSuffix(altName, ":$DATA") {
|
|
||||||
altName = altName[:len(altName)-len(":$DATA")]
|
|
||||||
}
|
|
||||||
if (bhdr.Attributes & winio.StreamSparseAttributes) == 0 {
|
|
||||||
hdr = &tar.Header{
|
|
||||||
Format: hdr.Format,
|
|
||||||
Name: name + altName,
|
|
||||||
Mode: hdr.Mode,
|
|
||||||
Typeflag: tar.TypeReg,
|
|
||||||
Size: bhdr.Size,
|
|
||||||
ModTime: hdr.ModTime,
|
|
||||||
AccessTime: hdr.AccessTime,
|
|
||||||
ChangeTime: hdr.ChangeTime,
|
|
||||||
}
|
|
||||||
err = t.WriteHeader(hdr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = io.Copy(t, br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Unsupported for now, since the size of the alternate stream is not present
|
// Unsupported for now, since the size of the alternate stream is not present
|
||||||
// in the backup stream until after the data has been read.
|
// in the backup stream until after the data has been read.
|
||||||
return fmt.Errorf("%s: tar of sparse alternate data streams is unsupported", name)
|
return fmt.Errorf("%s: tar of sparse alternate data streams is unsupported", name)
|
||||||
}
|
}
|
||||||
|
altName := strings.TrimSuffix(bhdr.Name, ":$DATA")
|
||||||
|
hdr = &tar.Header{
|
||||||
|
Format: hdr.Format,
|
||||||
|
Name: name + altName,
|
||||||
|
Mode: hdr.Mode,
|
||||||
|
Typeflag: tar.TypeReg,
|
||||||
|
Size: bhdr.Size,
|
||||||
|
ModTime: hdr.ModTime,
|
||||||
|
AccessTime: hdr.AccessTime,
|
||||||
|
ChangeTime: hdr.ChangeTime,
|
||||||
|
}
|
||||||
|
err = t.WriteHeader(hdr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(t, br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case winio.BackupEaData, winio.BackupLink, winio.BackupPropertyData, winio.BackupObjectId, winio.BackupTxfsData:
|
case winio.BackupEaData, winio.BackupLink, winio.BackupPropertyData, winio.BackupObjectId, winio.BackupTxfsData:
|
||||||
// ignore these streams
|
// ignore these streams
|
||||||
default:
|
default:
|
||||||
@ -413,7 +406,7 @@ func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *win
|
|||||||
}
|
}
|
||||||
fileInfo.CreationTime = windows.NsecToFiletime(creationTime.UnixNano())
|
fileInfo.CreationTime = windows.NsecToFiletime(creationTime.UnixNano())
|
||||||
}
|
}
|
||||||
return
|
return name, size, fileInfo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteBackupStreamFromTarFile writes a Win32 backup stream from the current tar file. Since this function may process multiple
|
// WriteBackupStreamFromTarFile writes a Win32 backup stream from the current tar file. Since this function may process multiple
|
||||||
@ -474,7 +467,6 @@ func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA {
|
if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA {
|
||||||
|
22
vendor/github.com/Microsoft/go-winio/doc.go
generated
vendored
Normal file
22
vendor/github.com/Microsoft/go-winio/doc.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// This package provides utilities for efficiently performing Win32 IO operations in Go.
|
||||||
|
// Currently, this package is provides support for genreal IO and management of
|
||||||
|
// - named pipes
|
||||||
|
// - files
|
||||||
|
// - [Hyper-V sockets]
|
||||||
|
//
|
||||||
|
// This code is similar to Go's [net] package, and uses IO completion ports to avoid
|
||||||
|
// blocking IO on system threads, allowing Go to reuse the thread to schedule other goroutines.
|
||||||
|
//
|
||||||
|
// This limits support to Windows Vista and newer operating systems.
|
||||||
|
//
|
||||||
|
// Additionally, this package provides support for:
|
||||||
|
// - creating and managing GUIDs
|
||||||
|
// - writing to [ETW]
|
||||||
|
// - opening and manageing VHDs
|
||||||
|
// - parsing [Windows Image files]
|
||||||
|
// - auto-generating Win32 API code
|
||||||
|
//
|
||||||
|
// [Hyper-V sockets]: https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service
|
||||||
|
// [ETW]: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-
|
||||||
|
// [Windows Image files]: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/work-with-windows-images
|
||||||
|
package winio
|
8
vendor/github.com/Microsoft/go-winio/ea.go
generated
vendored
8
vendor/github.com/Microsoft/go-winio/ea.go
generated
vendored
@ -33,7 +33,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
|
|||||||
err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
|
err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errInvalidEaBuffer
|
err = errInvalidEaBuffer
|
||||||
return
|
return ea, nb, err
|
||||||
}
|
}
|
||||||
|
|
||||||
nameOffset := fileFullEaInformationSize
|
nameOffset := fileFullEaInformationSize
|
||||||
@ -43,7 +43,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
|
|||||||
nextOffset := int(info.NextEntryOffset)
|
nextOffset := int(info.NextEntryOffset)
|
||||||
if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
|
if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
|
||||||
err = errInvalidEaBuffer
|
err = errInvalidEaBuffer
|
||||||
return
|
return ea, nb, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ea.Name = string(b[nameOffset : nameOffset+nameLen])
|
ea.Name = string(b[nameOffset : nameOffset+nameLen])
|
||||||
@ -52,7 +52,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
|
|||||||
if info.NextEntryOffset != 0 {
|
if info.NextEntryOffset != 0 {
|
||||||
nb = b[info.NextEntryOffset:]
|
nb = b[info.NextEntryOffset:]
|
||||||
}
|
}
|
||||||
return
|
return ea, nb, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
|
// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
|
||||||
@ -67,7 +67,7 @@ func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
|
|||||||
eas = append(eas, ea)
|
eas = append(eas, ea)
|
||||||
b = nb
|
b = nb
|
||||||
}
|
}
|
||||||
return
|
return eas, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
|
func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
|
||||||
|
66
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
66
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
@ -11,6 +11,8 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
|
//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
|
||||||
@ -24,6 +26,8 @@ type atomicBool int32
|
|||||||
func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
|
func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
|
||||||
func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) }
|
func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) }
|
||||||
func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) }
|
func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) }
|
||||||
|
|
||||||
|
//revive:disable-next-line:predeclared Keep "new" to maintain consistency with "atomic" pkg
|
||||||
func (b *atomicBool) swap(new bool) bool {
|
func (b *atomicBool) swap(new bool) bool {
|
||||||
var newInt int32
|
var newInt int32
|
||||||
if new {
|
if new {
|
||||||
@ -32,11 +36,6 @@ func (b *atomicBool) swap(new bool) bool {
|
|||||||
return atomic.SwapInt32((*int32)(b), newInt) == 1
|
return atomic.SwapInt32((*int32)(b), newInt) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1
|
|
||||||
cFILE_SKIP_SET_EVENT_ON_HANDLE = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrFileClosed = errors.New("file has already been closed")
|
ErrFileClosed = errors.New("file has already been closed")
|
||||||
ErrTimeout = &timeoutError{}
|
ErrTimeout = &timeoutError{}
|
||||||
@ -44,28 +43,28 @@ var (
|
|||||||
|
|
||||||
type timeoutError struct{}
|
type timeoutError struct{}
|
||||||
|
|
||||||
func (e *timeoutError) Error() string { return "i/o timeout" }
|
func (*timeoutError) Error() string { return "i/o timeout" }
|
||||||
func (e *timeoutError) Timeout() bool { return true }
|
func (*timeoutError) Timeout() bool { return true }
|
||||||
func (e *timeoutError) Temporary() bool { return true }
|
func (*timeoutError) Temporary() bool { return true }
|
||||||
|
|
||||||
type timeoutChan chan struct{}
|
type timeoutChan chan struct{}
|
||||||
|
|
||||||
var ioInitOnce sync.Once
|
var ioInitOnce sync.Once
|
||||||
var ioCompletionPort syscall.Handle
|
var ioCompletionPort syscall.Handle
|
||||||
|
|
||||||
// ioResult contains the result of an asynchronous IO operation
|
// ioResult contains the result of an asynchronous IO operation.
|
||||||
type ioResult struct {
|
type ioResult struct {
|
||||||
bytes uint32
|
bytes uint32
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ioOperation represents an outstanding asynchronous Win32 IO
|
// ioOperation represents an outstanding asynchronous Win32 IO.
|
||||||
type ioOperation struct {
|
type ioOperation struct {
|
||||||
o syscall.Overlapped
|
o syscall.Overlapped
|
||||||
ch chan ioResult
|
ch chan ioResult
|
||||||
}
|
}
|
||||||
|
|
||||||
func initIo() {
|
func initIO() {
|
||||||
h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
|
h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -94,15 +93,15 @@ type deadlineHandler struct {
|
|||||||
timedout atomicBool
|
timedout atomicBool
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeWin32File makes a new win32File from an existing file handle
|
// makeWin32File makes a new win32File from an existing file handle.
|
||||||
func makeWin32File(h syscall.Handle) (*win32File, error) {
|
func makeWin32File(h syscall.Handle) (*win32File, error) {
|
||||||
f := &win32File{handle: h}
|
f := &win32File{handle: h}
|
||||||
ioInitOnce.Do(initIo)
|
ioInitOnce.Do(initIO)
|
||||||
_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
|
_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE)
|
err = setFileCompletionNotificationModes(h, windows.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS|windows.FILE_SKIP_SET_EVENT_ON_HANDLE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -121,14 +120,14 @@ func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// closeHandle closes the resources associated with a Win32 handle
|
// closeHandle closes the resources associated with a Win32 handle.
|
||||||
func (f *win32File) closeHandle() {
|
func (f *win32File) closeHandle() {
|
||||||
f.wgLock.Lock()
|
f.wgLock.Lock()
|
||||||
// Atomically set that we are closing, releasing the resources only once.
|
// Atomically set that we are closing, releasing the resources only once.
|
||||||
if !f.closing.swap(true) {
|
if !f.closing.swap(true) {
|
||||||
f.wgLock.Unlock()
|
f.wgLock.Unlock()
|
||||||
// cancel all IO and wait for it to complete
|
// cancel all IO and wait for it to complete
|
||||||
cancelIoEx(f.handle, nil)
|
_ = cancelIoEx(f.handle, nil)
|
||||||
f.wg.Wait()
|
f.wg.Wait()
|
||||||
// at this point, no new IO can start
|
// at this point, no new IO can start
|
||||||
syscall.Close(f.handle)
|
syscall.Close(f.handle)
|
||||||
@ -144,14 +143,14 @@ func (f *win32File) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsClosed checks if the file has been closed
|
// IsClosed checks if the file has been closed.
|
||||||
func (f *win32File) IsClosed() bool {
|
func (f *win32File) IsClosed() bool {
|
||||||
return f.closing.isSet()
|
return f.closing.isSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepareIo prepares for a new IO operation.
|
// prepareIO prepares for a new IO operation.
|
||||||
// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
|
// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
|
||||||
func (f *win32File) prepareIo() (*ioOperation, error) {
|
func (f *win32File) prepareIO() (*ioOperation, error) {
|
||||||
f.wgLock.RLock()
|
f.wgLock.RLock()
|
||||||
if f.closing.isSet() {
|
if f.closing.isSet() {
|
||||||
f.wgLock.RUnlock()
|
f.wgLock.RUnlock()
|
||||||
@ -164,7 +163,7 @@ func (f *win32File) prepareIo() (*ioOperation, error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ioCompletionProcessor processes completed async IOs forever
|
// ioCompletionProcessor processes completed async IOs forever.
|
||||||
func ioCompletionProcessor(h syscall.Handle) {
|
func ioCompletionProcessor(h syscall.Handle) {
|
||||||
for {
|
for {
|
||||||
var bytes uint32
|
var bytes uint32
|
||||||
@ -178,15 +177,17 @@ func ioCompletionProcessor(h syscall.Handle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// asyncIo processes the return value from ReadFile or WriteFile, blocking until
|
// todo: helsaawy - create an asyncIO version that takes a context
|
||||||
|
|
||||||
|
// asyncIO processes the return value from ReadFile or WriteFile, blocking until
|
||||||
// the operation has actually completed.
|
// the operation has actually completed.
|
||||||
func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
|
func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
|
||||||
if err != syscall.ERROR_IO_PENDING {
|
if err != syscall.ERROR_IO_PENDING { //nolint:errorlint // err is Errno
|
||||||
return int(bytes), err
|
return int(bytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.closing.isSet() {
|
if f.closing.isSet() {
|
||||||
cancelIoEx(f.handle, &c.o)
|
_ = cancelIoEx(f.handle, &c.o)
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeout timeoutChan
|
var timeout timeoutChan
|
||||||
@ -200,7 +201,7 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
|
|||||||
select {
|
select {
|
||||||
case r = <-c.ch:
|
case r = <-c.ch:
|
||||||
err = r.err
|
err = r.err
|
||||||
if err == syscall.ERROR_OPERATION_ABORTED {
|
if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
|
||||||
if f.closing.isSet() {
|
if f.closing.isSet() {
|
||||||
err = ErrFileClosed
|
err = ErrFileClosed
|
||||||
}
|
}
|
||||||
@ -210,10 +211,10 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
|
|||||||
err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
|
err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
|
||||||
}
|
}
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
cancelIoEx(f.handle, &c.o)
|
_ = cancelIoEx(f.handle, &c.o)
|
||||||
r = <-c.ch
|
r = <-c.ch
|
||||||
err = r.err
|
err = r.err
|
||||||
if err == syscall.ERROR_OPERATION_ABORTED {
|
if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
|
||||||
err = ErrTimeout
|
err = ErrTimeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,13 +222,14 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
|
|||||||
// runtime.KeepAlive is needed, as c is passed via native
|
// runtime.KeepAlive is needed, as c is passed via native
|
||||||
// code to ioCompletionProcessor, c must remain alive
|
// code to ioCompletionProcessor, c must remain alive
|
||||||
// until the channel read is complete.
|
// until the channel read is complete.
|
||||||
|
// todo: (de)allocate *ioOperation via win32 heap functions, instead of needing to KeepAlive?
|
||||||
runtime.KeepAlive(c)
|
runtime.KeepAlive(c)
|
||||||
return int(r.bytes), err
|
return int(r.bytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read reads from a file handle.
|
// Read reads from a file handle.
|
||||||
func (f *win32File) Read(b []byte) (int, error) {
|
func (f *win32File) Read(b []byte) (int, error) {
|
||||||
c, err := f.prepareIo()
|
c, err := f.prepareIO()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -239,13 +241,13 @@ func (f *win32File) Read(b []byte) (int, error) {
|
|||||||
|
|
||||||
var bytes uint32
|
var bytes uint32
|
||||||
err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
|
err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
|
||||||
n, err := f.asyncIo(c, &f.readDeadline, bytes, err)
|
n, err := f.asyncIO(c, &f.readDeadline, bytes, err)
|
||||||
runtime.KeepAlive(b)
|
runtime.KeepAlive(b)
|
||||||
|
|
||||||
// Handle EOF conditions.
|
// Handle EOF conditions.
|
||||||
if err == nil && n == 0 && len(b) != 0 {
|
if err == nil && n == 0 && len(b) != 0 {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
} else if err == syscall.ERROR_BROKEN_PIPE {
|
} else if err == syscall.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
} else {
|
} else {
|
||||||
return n, err
|
return n, err
|
||||||
@ -254,7 +256,7 @@ func (f *win32File) Read(b []byte) (int, error) {
|
|||||||
|
|
||||||
// Write writes to a file handle.
|
// Write writes to a file handle.
|
||||||
func (f *win32File) Write(b []byte) (int, error) {
|
func (f *win32File) Write(b []byte) (int, error) {
|
||||||
c, err := f.prepareIo()
|
c, err := f.prepareIO()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -266,7 +268,7 @@ func (f *win32File) Write(b []byte) (int, error) {
|
|||||||
|
|
||||||
var bytes uint32
|
var bytes uint32
|
||||||
err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
|
err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
|
||||||
n, err := f.asyncIo(c, &f.writeDeadline, bytes, err)
|
n, err := f.asyncIO(c, &f.writeDeadline, bytes, err)
|
||||||
runtime.KeepAlive(b)
|
runtime.KeepAlive(b)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
29
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
29
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package winio
|
package winio
|
||||||
@ -14,13 +15,18 @@ import (
|
|||||||
type FileBasicInfo struct {
|
type FileBasicInfo struct {
|
||||||
CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
|
CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
|
||||||
FileAttributes uint32
|
FileAttributes uint32
|
||||||
pad uint32 // padding
|
_ uint32 // padding
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFileBasicInfo retrieves times and attributes for a file.
|
// GetFileBasicInfo retrieves times and attributes for a file.
|
||||||
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
|
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
|
||||||
bi := &FileBasicInfo{}
|
bi := &FileBasicInfo{}
|
||||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
|
if err := windows.GetFileInformationByHandleEx(
|
||||||
|
windows.Handle(f.Fd()),
|
||||||
|
windows.FileBasicInfo,
|
||||||
|
(*byte)(unsafe.Pointer(bi)),
|
||||||
|
uint32(unsafe.Sizeof(*bi)),
|
||||||
|
); err != nil {
|
||||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||||
}
|
}
|
||||||
runtime.KeepAlive(f)
|
runtime.KeepAlive(f)
|
||||||
@ -29,7 +35,12 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
|
|||||||
|
|
||||||
// SetFileBasicInfo sets times and attributes for a file.
|
// SetFileBasicInfo sets times and attributes for a file.
|
||||||
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
|
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
|
||||||
if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
|
if err := windows.SetFileInformationByHandle(
|
||||||
|
windows.Handle(f.Fd()),
|
||||||
|
windows.FileBasicInfo,
|
||||||
|
(*byte)(unsafe.Pointer(bi)),
|
||||||
|
uint32(unsafe.Sizeof(*bi)),
|
||||||
|
); err != nil {
|
||||||
return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
|
return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
|
||||||
}
|
}
|
||||||
runtime.KeepAlive(f)
|
runtime.KeepAlive(f)
|
||||||
@ -48,7 +59,10 @@ type FileStandardInfo struct {
|
|||||||
// GetFileStandardInfo retrieves ended information for the file.
|
// GetFileStandardInfo retrieves ended information for the file.
|
||||||
func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
|
func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
|
||||||
si := &FileStandardInfo{}
|
si := &FileStandardInfo{}
|
||||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil {
|
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()),
|
||||||
|
windows.FileStandardInfo,
|
||||||
|
(*byte)(unsafe.Pointer(si)),
|
||||||
|
uint32(unsafe.Sizeof(*si))); err != nil {
|
||||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||||
}
|
}
|
||||||
runtime.KeepAlive(f)
|
runtime.KeepAlive(f)
|
||||||
@ -65,7 +79,12 @@ type FileIDInfo struct {
|
|||||||
// GetFileID retrieves the unique (volume, file ID) pair for a file.
|
// GetFileID retrieves the unique (volume, file ID) pair for a file.
|
||||||
func GetFileID(f *os.File) (*FileIDInfo, error) {
|
func GetFileID(f *os.File) (*FileIDInfo, error) {
|
||||||
fileID := &FileIDInfo{}
|
fileID := &FileIDInfo{}
|
||||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
|
if err := windows.GetFileInformationByHandleEx(
|
||||||
|
windows.Handle(f.Fd()),
|
||||||
|
windows.FileIdInfo,
|
||||||
|
(*byte)(unsafe.Pointer(fileID)),
|
||||||
|
uint32(unsafe.Sizeof(*fileID)),
|
||||||
|
); err != nil {
|
||||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||||
}
|
}
|
||||||
runtime.KeepAlive(f)
|
runtime.KeepAlive(f)
|
||||||
|
345
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
345
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
@ -4,6 +4,8 @@
|
|||||||
package winio
|
package winio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@ -12,16 +14,87 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/internal/socket"
|
||||||
"github.com/Microsoft/go-winio/pkg/guid"
|
"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
|
||||||
|
|
||||||
const (
|
// Well known Service and VM IDs
|
||||||
afHvSock = 34 // AF_HYPERV
|
//https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service#vmid-wildcards
|
||||||
|
|
||||||
socketError = ^uintptr(0)
|
// HvsockGUIDWildcard is the wildcard VmId for accepting connections from all partitions.
|
||||||
)
|
func HvsockGUIDWildcard() guid.GUID { // 00000000-0000-0000-0000-000000000000
|
||||||
|
return guid.GUID{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HvsockGUIDBroadcast is the wildcard VmId for broadcasting sends to all partitions.
|
||||||
|
func HvsockGUIDBroadcast() guid.GUID { //ffffffff-ffff-ffff-ffff-ffffffffffff
|
||||||
|
return guid.GUID{
|
||||||
|
Data1: 0xffffffff,
|
||||||
|
Data2: 0xffff,
|
||||||
|
Data3: 0xffff,
|
||||||
|
Data4: [8]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HvsockGUIDLoopback is the Loopback VmId for accepting connections to the same partition as the connector.
|
||||||
|
func HvsockGUIDLoopback() guid.GUID { // e0e16197-dd56-4a10-9195-5ee7a155a838
|
||||||
|
return guid.GUID{
|
||||||
|
Data1: 0xe0e16197,
|
||||||
|
Data2: 0xdd56,
|
||||||
|
Data3: 0x4a10,
|
||||||
|
Data4: [8]uint8{0x91, 0x95, 0x5e, 0xe7, 0xa1, 0x55, 0xa8, 0x38},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HvsockGUIDSiloHost is the address of a silo's host partition:
|
||||||
|
// - The silo host of a hosted silo is the utility VM.
|
||||||
|
// - The silo host of a silo on a physical host is the physical host.
|
||||||
|
func HvsockGUIDSiloHost() guid.GUID { // 36bd0c5c-7276-4223-88ba-7d03b654c568
|
||||||
|
return guid.GUID{
|
||||||
|
Data1: 0x36bd0c5c,
|
||||||
|
Data2: 0x7276,
|
||||||
|
Data3: 0x4223,
|
||||||
|
Data4: [8]byte{0x88, 0xba, 0x7d, 0x03, 0xb6, 0x54, 0xc5, 0x68},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HvsockGUIDChildren is the wildcard VmId for accepting connections from the connector's child partitions.
|
||||||
|
func HvsockGUIDChildren() guid.GUID { // 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd
|
||||||
|
return guid.GUID{
|
||||||
|
Data1: 0x90db8b89,
|
||||||
|
Data2: 0xd35,
|
||||||
|
Data3: 0x4f79,
|
||||||
|
Data4: [8]uint8{0x8c, 0xe9, 0x49, 0xea, 0xa, 0xc8, 0xb7, 0xcd},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HvsockGUIDParent is the wildcard VmId for accepting connections from the connector's parent partition.
|
||||||
|
// Listening on this VmId accepts connection from:
|
||||||
|
// - Inside silos: silo host partition.
|
||||||
|
// - Inside hosted silo: host of the VM.
|
||||||
|
// - Inside VM: VM host.
|
||||||
|
// - Physical host: Not supported.
|
||||||
|
func HvsockGUIDParent() guid.GUID { // a42e7cda-d03f-480c-9cc2-a4de20abb878
|
||||||
|
return guid.GUID{
|
||||||
|
Data1: 0xa42e7cda,
|
||||||
|
Data2: 0xd03f,
|
||||||
|
Data3: 0x480c,
|
||||||
|
Data4: [8]uint8{0x9c, 0xc2, 0xa4, 0xde, 0x20, 0xab, 0xb8, 0x78},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hvsockVsockServiceTemplate is the Service GUID used for the VSOCK protocol.
|
||||||
|
func hvsockVsockServiceTemplate() guid.GUID { // 00000000-facb-11e6-bd58-64006a7986d3
|
||||||
|
return guid.GUID{
|
||||||
|
Data2: 0xfacb,
|
||||||
|
Data3: 0x11e6,
|
||||||
|
Data4: [8]uint8{0xbd, 0x58, 0x64, 0x00, 0x6a, 0x79, 0x86, 0xd3},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// An HvsockAddr is an address for a AF_HYPERV socket.
|
// An HvsockAddr is an address for a AF_HYPERV socket.
|
||||||
type HvsockAddr struct {
|
type HvsockAddr struct {
|
||||||
@ -36,8 +109,10 @@ type rawHvsockAddr struct {
|
|||||||
ServiceID guid.GUID
|
ServiceID guid.GUID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ socket.RawSockaddr = &rawHvsockAddr{}
|
||||||
|
|
||||||
// Network returns the address's network name, "hvsock".
|
// Network returns the address's network name, "hvsock".
|
||||||
func (addr *HvsockAddr) Network() string {
|
func (*HvsockAddr) Network() string {
|
||||||
return "hvsock"
|
return "hvsock"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,14 +122,14 @@ func (addr *HvsockAddr) String() string {
|
|||||||
|
|
||||||
// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
|
// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
|
||||||
func VsockServiceID(port uint32) guid.GUID {
|
func VsockServiceID(port uint32) guid.GUID {
|
||||||
g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3")
|
g := hvsockVsockServiceTemplate() // make a copy
|
||||||
g.Data1 = port
|
g.Data1 = port
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (addr *HvsockAddr) raw() rawHvsockAddr {
|
func (addr *HvsockAddr) raw() rawHvsockAddr {
|
||||||
return rawHvsockAddr{
|
return rawHvsockAddr{
|
||||||
Family: afHvSock,
|
Family: afHVSock,
|
||||||
VMID: addr.VMID,
|
VMID: addr.VMID,
|
||||||
ServiceID: addr.ServiceID,
|
ServiceID: addr.ServiceID,
|
||||||
}
|
}
|
||||||
@ -65,20 +140,48 @@ func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) {
|
|||||||
addr.ServiceID = raw.ServiceID
|
addr.ServiceID = raw.ServiceID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sockaddr returns a pointer to and the size of this struct.
|
||||||
|
//
|
||||||
|
// Implements the [socket.RawSockaddr] interface, and allows use in
|
||||||
|
// [socket.Bind] and [socket.ConnectEx].
|
||||||
|
func (r *rawHvsockAddr) Sockaddr() (unsafe.Pointer, int32, error) {
|
||||||
|
return unsafe.Pointer(r), int32(unsafe.Sizeof(rawHvsockAddr{})), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sockaddr interface allows use with `sockets.Bind()` and `.ConnectEx()`.
|
||||||
|
func (r *rawHvsockAddr) FromBytes(b []byte) error {
|
||||||
|
n := int(unsafe.Sizeof(rawHvsockAddr{}))
|
||||||
|
|
||||||
|
if len(b) < n {
|
||||||
|
return fmt.Errorf("got %d, want %d: %w", len(b), n, socket.ErrBufferSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(unsafe.Slice((*byte)(unsafe.Pointer(r)), n), b[:n])
|
||||||
|
if r.Family != afHVSock {
|
||||||
|
return fmt.Errorf("got %d, want %d: %w", r.Family, afHVSock, socket.ErrAddrFamily)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// HvsockListener is a socket listener for the AF_HYPERV address family.
|
// HvsockListener is a socket listener for the AF_HYPERV address family.
|
||||||
type HvsockListener struct {
|
type HvsockListener struct {
|
||||||
sock *win32File
|
sock *win32File
|
||||||
addr HvsockAddr
|
addr HvsockAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ net.Listener = &HvsockListener{}
|
||||||
|
|
||||||
// HvsockConn is a connected socket of the AF_HYPERV address family.
|
// HvsockConn is a connected socket of the AF_HYPERV address family.
|
||||||
type HvsockConn struct {
|
type HvsockConn struct {
|
||||||
sock *win32File
|
sock *win32File
|
||||||
local, remote HvsockAddr
|
local, remote HvsockAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHvSocket() (*win32File, error) {
|
var _ net.Conn = &HvsockConn{}
|
||||||
fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1)
|
|
||||||
|
func newHVSocket() (*win32File, error) {
|
||||||
|
fd, err := syscall.Socket(afHVSock, syscall.SOCK_STREAM, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, os.NewSyscallError("socket", err)
|
return nil, os.NewSyscallError("socket", err)
|
||||||
}
|
}
|
||||||
@ -94,12 +197,12 @@ func newHvSocket() (*win32File, error) {
|
|||||||
// ListenHvsock listens for connections on the specified hvsock address.
|
// ListenHvsock listens for connections on the specified hvsock address.
|
||||||
func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
|
func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
|
||||||
l := &HvsockListener{addr: *addr}
|
l := &HvsockListener{addr: *addr}
|
||||||
sock, err := newHvSocket()
|
sock, err := newHVSocket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, l.opErr("listen", err)
|
return nil, l.opErr("listen", err)
|
||||||
}
|
}
|
||||||
sa := addr.raw()
|
sa := addr.raw()
|
||||||
err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa)))
|
err = socket.Bind(windows.Handle(sock.handle), &sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, l.opErr("listen", os.NewSyscallError("socket", err))
|
return nil, l.opErr("listen", os.NewSyscallError("socket", err))
|
||||||
}
|
}
|
||||||
@ -121,7 +224,7 @@ func (l *HvsockListener) Addr() net.Addr {
|
|||||||
|
|
||||||
// Accept waits for the next connection and returns it.
|
// Accept waits for the next connection and returns it.
|
||||||
func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
||||||
sock, err := newHvSocket()
|
sock, err := newHVSocket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, l.opErr("accept", err)
|
return nil, l.opErr("accept", err)
|
||||||
}
|
}
|
||||||
@ -130,27 +233,42 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
|||||||
sock.Close()
|
sock.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
c, err := l.sock.prepareIo()
|
c, err := l.sock.prepareIO()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, l.opErr("accept", err)
|
return nil, l.opErr("accept", err)
|
||||||
}
|
}
|
||||||
defer l.sock.wg.Done()
|
defer l.sock.wg.Done()
|
||||||
|
|
||||||
// AcceptEx, per documentation, requires an extra 16 bytes per address.
|
// AcceptEx, per documentation, requires an extra 16 bytes per address.
|
||||||
|
//
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex
|
||||||
const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
|
const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
|
||||||
var addrbuf [addrlen * 2]byte
|
var addrbuf [addrlen * 2]byte
|
||||||
|
|
||||||
var bytes uint32
|
var bytes uint32
|
||||||
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o)
|
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /*rxdatalen*/, addrlen, addrlen, &bytes, &c.o)
|
||||||
_, err = l.sock.asyncIo(c, nil, bytes, err)
|
if _, err = l.sock.asyncIO(c, nil, bytes, err); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
|
return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
conn := &HvsockConn{
|
conn := &HvsockConn{
|
||||||
sock: sock,
|
sock: sock,
|
||||||
}
|
}
|
||||||
|
// The local address returned in the AcceptEx buffer is the same as the Listener socket's
|
||||||
|
// address. However, the service GUID reported by GetSockName is different from the Listeners
|
||||||
|
// socket, and is sometimes the same as the local address of the socket that dialed the
|
||||||
|
// address, with the service GUID.Data1 incremented, but othertimes is different.
|
||||||
|
// todo: does the local address matter? is the listener's address or the actual address appropriate?
|
||||||
conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
|
conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
|
||||||
conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
|
conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
|
||||||
|
|
||||||
|
// initialize the accepted socket and update its properties with those of the listening socket
|
||||||
|
if err = windows.Setsockopt(windows.Handle(sock.handle),
|
||||||
|
windows.SOL_SOCKET, windows.SO_UPDATE_ACCEPT_CONTEXT,
|
||||||
|
(*byte)(unsafe.Pointer(&l.sock.handle)), int32(unsafe.Sizeof(l.sock.handle))); err != nil {
|
||||||
|
return nil, conn.opErr("accept", os.NewSyscallError("setsockopt", err))
|
||||||
|
}
|
||||||
|
|
||||||
sock = nil
|
sock = nil
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
@ -160,43 +278,171 @@ func (l *HvsockListener) Close() error {
|
|||||||
return l.sock.Close()
|
return l.sock.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Need to finish ConnectEx handling
|
// HvsockDialer configures and dials a Hyper-V Socket (ie, [HvsockConn]).
|
||||||
func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) {
|
type HvsockDialer struct {
|
||||||
sock, err := newHvSocket()
|
// Deadline is the time the Dial operation must connect before erroring.
|
||||||
|
Deadline time.Time
|
||||||
|
|
||||||
|
// Retries is the number of additional connects to try if the connection times out, is refused,
|
||||||
|
// or the host is unreachable
|
||||||
|
Retries uint
|
||||||
|
|
||||||
|
// RetryWait is the time to wait after a connection error to retry
|
||||||
|
RetryWait time.Duration
|
||||||
|
|
||||||
|
rt *time.Timer // redial wait timer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial the Hyper-V socket at addr.
|
||||||
|
//
|
||||||
|
// See [HvsockDialer.Dial] for more information.
|
||||||
|
func Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) {
|
||||||
|
return (&HvsockDialer{}).Dial(ctx, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial attempts to connect to the Hyper-V socket at addr, and returns a connection if successful.
|
||||||
|
// Will attempt (HvsockDialer).Retries if dialing fails, waiting (HvsockDialer).RetryWait between
|
||||||
|
// retries.
|
||||||
|
//
|
||||||
|
// Dialing can be cancelled either by providing (HvsockDialer).Deadline, or cancelling ctx.
|
||||||
|
func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) {
|
||||||
|
op := "dial"
|
||||||
|
// create the conn early to use opErr()
|
||||||
|
conn = &HvsockConn{
|
||||||
|
remote: *addr,
|
||||||
|
}
|
||||||
|
|
||||||
|
if !d.Deadline.IsZero() {
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
ctx, cancel = context.WithDeadline(ctx, d.Deadline)
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
// preemptive timeout/cancellation check
|
||||||
|
if err = ctx.Err(); err != nil {
|
||||||
|
return nil, conn.opErr(op, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sock, err := newHVSocket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, conn.opErr(op, err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if sock != nil {
|
if sock != nil {
|
||||||
sock.Close()
|
sock.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
c, err := sock.prepareIo()
|
|
||||||
|
sa := addr.raw()
|
||||||
|
err = socket.Bind(windows.Handle(sock.handle), &sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, conn.opErr(op, os.NewSyscallError("bind", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := sock.prepareIO()
|
||||||
|
if err != nil {
|
||||||
|
return nil, conn.opErr(op, err)
|
||||||
}
|
}
|
||||||
defer sock.wg.Done()
|
defer sock.wg.Done()
|
||||||
var bytes uint32
|
var bytes uint32
|
||||||
err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o)
|
for i := uint(0); i <= d.Retries; i++ {
|
||||||
_, err = sock.asyncIo(ctx, c, nil, bytes, err)
|
err = socket.ConnectEx(
|
||||||
|
windows.Handle(sock.handle),
|
||||||
|
&sa,
|
||||||
|
nil, // sendBuf
|
||||||
|
0, // sendDataLen
|
||||||
|
&bytes,
|
||||||
|
(*windows.Overlapped)(unsafe.Pointer(&c.o)))
|
||||||
|
_, err = sock.asyncIO(c, nil, bytes, err)
|
||||||
|
if i < d.Retries && canRedial(err) {
|
||||||
|
if err = d.redialWait(ctx); err == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, conn.opErr(op, os.NewSyscallError("connectex", err))
|
||||||
}
|
}
|
||||||
conn := &HvsockConn{
|
|
||||||
sock: sock,
|
// update the connection properties, so shutdown can be used
|
||||||
remote: *addr,
|
if err = windows.Setsockopt(
|
||||||
|
windows.Handle(sock.handle),
|
||||||
|
windows.SOL_SOCKET,
|
||||||
|
windows.SO_UPDATE_CONNECT_CONTEXT,
|
||||||
|
nil, // optvalue
|
||||||
|
0, // optlen
|
||||||
|
); err != nil {
|
||||||
|
return nil, conn.opErr(op, os.NewSyscallError("setsockopt", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the local name
|
||||||
|
var sal rawHvsockAddr
|
||||||
|
err = socket.GetSockName(windows.Handle(sock.handle), &sal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, conn.opErr(op, os.NewSyscallError("getsockname", err))
|
||||||
|
}
|
||||||
|
conn.local.fromRaw(&sal)
|
||||||
|
|
||||||
|
// one last check for timeout, since asyncIO doesn't check the context
|
||||||
|
if err = ctx.Err(); err != nil {
|
||||||
|
return nil, conn.opErr(op, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.sock = sock
|
||||||
sock = nil
|
sock = nil
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
// redialWait waits before attempting to redial, resetting the timer as appropriate.
|
||||||
|
func (d *HvsockDialer) redialWait(ctx context.Context) (err error) {
|
||||||
|
if d.RetryWait == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.rt == nil {
|
||||||
|
d.rt = time.NewTimer(d.RetryWait)
|
||||||
|
} else {
|
||||||
|
// should already be stopped and drained
|
||||||
|
d.rt.Reset(d.RetryWait)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-d.rt.C:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop and drain the timer
|
||||||
|
if !d.rt.Stop() {
|
||||||
|
<-d.rt.C
|
||||||
|
}
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
// assumes error is a plain, unwrapped syscall.Errno provided by direct syscall.
|
||||||
|
func canRedial(err error) bool {
|
||||||
|
//nolint:errorlint // guaranteed to be an Errno
|
||||||
|
switch err {
|
||||||
|
case windows.WSAECONNREFUSED, windows.WSAENETUNREACH, windows.WSAETIMEDOUT,
|
||||||
|
windows.ERROR_CONNECTION_REFUSED, windows.ERROR_CONNECTION_UNAVAIL:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (conn *HvsockConn) opErr(op string, err error) error {
|
func (conn *HvsockConn) opErr(op string, err error) error {
|
||||||
|
// translate from "file closed" to "socket closed"
|
||||||
|
if errors.Is(err, ErrFileClosed) {
|
||||||
|
err = socket.ErrSocketClosed
|
||||||
|
}
|
||||||
return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
|
return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conn *HvsockConn) Read(b []byte) (int, error) {
|
func (conn *HvsockConn) Read(b []byte) (int, error) {
|
||||||
c, err := conn.sock.prepareIo()
|
c, err := conn.sock.prepareIO()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, conn.opErr("read", err)
|
return 0, conn.opErr("read", err)
|
||||||
}
|
}
|
||||||
@ -204,10 +450,11 @@ func (conn *HvsockConn) Read(b []byte) (int, error) {
|
|||||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||||
var flags, bytes uint32
|
var flags, bytes uint32
|
||||||
err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
|
err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
|
||||||
n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err)
|
n, err := conn.sock.asyncIO(c, &conn.sock.readDeadline, bytes, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(syscall.Errno); ok {
|
var eno windows.Errno
|
||||||
err = os.NewSyscallError("wsarecv", err)
|
if errors.As(err, &eno) {
|
||||||
|
err = os.NewSyscallError("wsarecv", eno)
|
||||||
}
|
}
|
||||||
return 0, conn.opErr("read", err)
|
return 0, conn.opErr("read", err)
|
||||||
} else if n == 0 {
|
} else if n == 0 {
|
||||||
@ -230,7 +477,7 @@ func (conn *HvsockConn) Write(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (conn *HvsockConn) write(b []byte) (int, error) {
|
func (conn *HvsockConn) write(b []byte) (int, error) {
|
||||||
c, err := conn.sock.prepareIo()
|
c, err := conn.sock.prepareIO()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, conn.opErr("write", err)
|
return 0, conn.opErr("write", err)
|
||||||
}
|
}
|
||||||
@ -238,10 +485,11 @@ func (conn *HvsockConn) write(b []byte) (int, error) {
|
|||||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||||
var bytes uint32
|
var bytes uint32
|
||||||
err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
|
err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
|
||||||
n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err)
|
n, err := conn.sock.asyncIO(c, &conn.sock.writeDeadline, bytes, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(syscall.Errno); ok {
|
var eno windows.Errno
|
||||||
err = os.NewSyscallError("wsasend", err)
|
if errors.As(err, &eno) {
|
||||||
|
err = os.NewSyscallError("wsasend", eno)
|
||||||
}
|
}
|
||||||
return 0, conn.opErr("write", err)
|
return 0, conn.opErr("write", err)
|
||||||
}
|
}
|
||||||
@ -257,13 +505,19 @@ func (conn *HvsockConn) IsClosed() bool {
|
|||||||
return conn.sock.IsClosed()
|
return conn.sock.IsClosed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shutdown disables sending or receiving on a socket.
|
||||||
func (conn *HvsockConn) shutdown(how int) error {
|
func (conn *HvsockConn) shutdown(how int) error {
|
||||||
if conn.IsClosed() {
|
if conn.IsClosed() {
|
||||||
return ErrFileClosed
|
return socket.ErrSocketClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
err := syscall.Shutdown(conn.sock.handle, how)
|
err := syscall.Shutdown(conn.sock.handle, how)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// If the connection was closed, shutdowns fail with "not connected"
|
||||||
|
if errors.Is(err, windows.WSAENOTCONN) ||
|
||||||
|
errors.Is(err, windows.WSAESHUTDOWN) {
|
||||||
|
err = socket.ErrSocketClosed
|
||||||
|
}
|
||||||
return os.NewSyscallError("shutdown", err)
|
return os.NewSyscallError("shutdown", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -273,7 +527,7 @@ func (conn *HvsockConn) shutdown(how int) error {
|
|||||||
func (conn *HvsockConn) CloseRead() error {
|
func (conn *HvsockConn) CloseRead() error {
|
||||||
err := conn.shutdown(syscall.SHUT_RD)
|
err := conn.shutdown(syscall.SHUT_RD)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return conn.opErr("close", err)
|
return conn.opErr("closeread", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -283,7 +537,7 @@ func (conn *HvsockConn) CloseRead() error {
|
|||||||
func (conn *HvsockConn) CloseWrite() error {
|
func (conn *HvsockConn) CloseWrite() error {
|
||||||
err := conn.shutdown(syscall.SHUT_WR)
|
err := conn.shutdown(syscall.SHUT_WR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return conn.opErr("close", err)
|
return conn.opErr("closewrite", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -300,8 +554,13 @@ func (conn *HvsockConn) RemoteAddr() net.Addr {
|
|||||||
|
|
||||||
// SetDeadline implements the net.Conn SetDeadline method.
|
// SetDeadline implements the net.Conn SetDeadline method.
|
||||||
func (conn *HvsockConn) SetDeadline(t time.Time) error {
|
func (conn *HvsockConn) SetDeadline(t time.Time) error {
|
||||||
conn.SetReadDeadline(t)
|
// todo: implement `SetDeadline` for `win32File`
|
||||||
conn.SetWriteDeadline(t)
|
if err := conn.SetReadDeadline(t); err != nil {
|
||||||
|
return fmt.Errorf("set read deadline: %w", err)
|
||||||
|
}
|
||||||
|
if err := conn.SetWriteDeadline(t); err != nil {
|
||||||
|
return fmt.Errorf("set write deadline: %w", err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go
generated
vendored
Normal file
20
vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RawSockaddr allows structs to be used with [Bind] and [ConnectEx]. The
|
||||||
|
// struct must meet the Win32 sockaddr requirements specified here:
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/winsock/sockaddr-2
|
||||||
|
//
|
||||||
|
// Specifically, the struct size must be least larger than an int16 (unsigned short)
|
||||||
|
// for the address family.
|
||||||
|
type RawSockaddr interface {
|
||||||
|
// Sockaddr returns a pointer to the RawSockaddr and its struct size, allowing
|
||||||
|
// for the RawSockaddr's data to be overwritten by syscalls (if necessary).
|
||||||
|
//
|
||||||
|
// It is the callers responsibility to validate that the values are valid; invalid
|
||||||
|
// pointers or size can cause a panic.
|
||||||
|
Sockaddr() (unsafe.Pointer, int32, error)
|
||||||
|
}
|
179
vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
generated
vendored
Normal file
179
vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
generated
vendored
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/pkg/guid"
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go socket.go
|
||||||
|
|
||||||
|
//sys getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getsockname
|
||||||
|
//sys getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getpeername
|
||||||
|
//sys bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
|
||||||
|
|
||||||
|
const socketError = uintptr(^uint32(0))
|
||||||
|
|
||||||
|
var (
|
||||||
|
// todo(helsaawy): create custom error types to store the desired vs actual size and addr family?
|
||||||
|
|
||||||
|
ErrBufferSize = errors.New("buffer size")
|
||||||
|
ErrAddrFamily = errors.New("address family")
|
||||||
|
ErrInvalidPointer = errors.New("invalid pointer")
|
||||||
|
ErrSocketClosed = fmt.Errorf("socket closed: %w", net.ErrClosed)
|
||||||
|
)
|
||||||
|
|
||||||
|
// todo(helsaawy): replace these with generics, ie: GetSockName[S RawSockaddr](s windows.Handle) (S, error)
|
||||||
|
|
||||||
|
// GetSockName writes the local address of socket s to the [RawSockaddr] rsa.
|
||||||
|
// If rsa is not large enough, the [windows.WSAEFAULT] is returned.
|
||||||
|
func GetSockName(s windows.Handle, rsa RawSockaddr) error {
|
||||||
|
ptr, l, err := rsa.Sockaddr()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// although getsockname returns WSAEFAULT if the buffer is too small, it does not set
|
||||||
|
// &l to the correct size, so--apart from doubling the buffer repeatedly--there is no remedy
|
||||||
|
return getsockname(s, ptr, &l)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPeerName returns the remote address the socket is connected to.
|
||||||
|
//
|
||||||
|
// See [GetSockName] for more information.
|
||||||
|
func GetPeerName(s windows.Handle, rsa RawSockaddr) error {
|
||||||
|
ptr, l, err := rsa.Sockaddr()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getpeername(s, ptr, &l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Bind(s windows.Handle, rsa RawSockaddr) (err error) {
|
||||||
|
ptr, l, err := rsa.Sockaddr()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bind(s, ptr, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
// "golang.org/x/sys/windows".ConnectEx and .Bind only accept internal implementations of the
|
||||||
|
// their sockaddr interface, so they cannot be used with HvsockAddr
|
||||||
|
// Replicate functionality here from
|
||||||
|
// https://cs.opensource.google/go/x/sys/+/master:windows/syscall_windows.go
|
||||||
|
|
||||||
|
// The function pointers to `AcceptEx`, `ConnectEx` and `GetAcceptExSockaddrs` must be loaded at
|
||||||
|
// runtime via a WSAIoctl call:
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/Mswsock/nc-mswsock-lpfn_connectex#remarks
|
||||||
|
|
||||||
|
type runtimeFunc struct {
|
||||||
|
id guid.GUID
|
||||||
|
once sync.Once
|
||||||
|
addr uintptr
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *runtimeFunc) Load() error {
|
||||||
|
f.once.Do(func() {
|
||||||
|
var s windows.Handle
|
||||||
|
s, f.err = windows.Socket(windows.AF_INET, windows.SOCK_STREAM, windows.IPPROTO_TCP)
|
||||||
|
if f.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer windows.CloseHandle(s) //nolint:errcheck
|
||||||
|
|
||||||
|
var n uint32
|
||||||
|
f.err = windows.WSAIoctl(s,
|
||||||
|
windows.SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||||
|
(*byte)(unsafe.Pointer(&f.id)),
|
||||||
|
uint32(unsafe.Sizeof(f.id)),
|
||||||
|
(*byte)(unsafe.Pointer(&f.addr)),
|
||||||
|
uint32(unsafe.Sizeof(f.addr)),
|
||||||
|
&n,
|
||||||
|
nil, //overlapped
|
||||||
|
0, //completionRoutine
|
||||||
|
)
|
||||||
|
})
|
||||||
|
return f.err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// todo: add `AcceptEx` and `GetAcceptExSockaddrs`
|
||||||
|
WSAID_CONNECTEX = guid.GUID{ //revive:disable-line:var-naming ALL_CAPS
|
||||||
|
Data1: 0x25a207b9,
|
||||||
|
Data2: 0xddf3,
|
||||||
|
Data3: 0x4660,
|
||||||
|
Data4: [8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e},
|
||||||
|
}
|
||||||
|
|
||||||
|
connectExFunc = runtimeFunc{id: WSAID_CONNECTEX}
|
||||||
|
)
|
||||||
|
|
||||||
|
func ConnectEx(
|
||||||
|
fd windows.Handle,
|
||||||
|
rsa RawSockaddr,
|
||||||
|
sendBuf *byte,
|
||||||
|
sendDataLen uint32,
|
||||||
|
bytesSent *uint32,
|
||||||
|
overlapped *windows.Overlapped,
|
||||||
|
) error {
|
||||||
|
if err := connectExFunc.Load(); err != nil {
|
||||||
|
return fmt.Errorf("failed to load ConnectEx function pointer: %w", err)
|
||||||
|
}
|
||||||
|
ptr, n, err := rsa.Sockaddr()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOOL LpfnConnectex(
|
||||||
|
// [in] SOCKET s,
|
||||||
|
// [in] const sockaddr *name,
|
||||||
|
// [in] int namelen,
|
||||||
|
// [in, optional] PVOID lpSendBuffer,
|
||||||
|
// [in] DWORD dwSendDataLength,
|
||||||
|
// [out] LPDWORD lpdwBytesSent,
|
||||||
|
// [in] LPOVERLAPPED lpOverlapped
|
||||||
|
// )
|
||||||
|
|
||||||
|
func connectEx(
|
||||||
|
s windows.Handle,
|
||||||
|
name unsafe.Pointer,
|
||||||
|
namelen int32,
|
||||||
|
sendBuf *byte,
|
||||||
|
sendDataLen uint32,
|
||||||
|
bytesSent *uint32,
|
||||||
|
overlapped *windows.Overlapped,
|
||||||
|
) (err error) {
|
||||||
|
// todo: after upgrading to 1.18, switch from syscall.Syscall9 to syscall.SyscallN
|
||||||
|
r1, _, e1 := syscall.Syscall9(connectExFunc.addr,
|
||||||
|
7,
|
||||||
|
uintptr(s),
|
||||||
|
uintptr(name),
|
||||||
|
uintptr(namelen),
|
||||||
|
uintptr(unsafe.Pointer(sendBuf)),
|
||||||
|
uintptr(sendDataLen),
|
||||||
|
uintptr(unsafe.Pointer(bytesSent)),
|
||||||
|
uintptr(unsafe.Pointer(overlapped)),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
if r1 == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = error(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
72
vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
generated
vendored
Normal file
72
vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ unsafe.Pointer
|
||||||
|
|
||||||
|
// Do the interface allocations only once for common
|
||||||
|
// Errno values.
|
||||||
|
const (
|
||||||
|
errnoERROR_IO_PENDING = 997
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||||
|
errERROR_EINVAL error = syscall.EINVAL
|
||||||
|
)
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent
|
||||||
|
// allocations at runtime.
|
||||||
|
func errnoErr(e syscall.Errno) error {
|
||||||
|
switch e {
|
||||||
|
case 0:
|
||||||
|
return errERROR_EINVAL
|
||||||
|
case errnoERROR_IO_PENDING:
|
||||||
|
return errERROR_IO_PENDING
|
||||||
|
}
|
||||||
|
// TODO: add more here, after collecting data on the common
|
||||||
|
// error values see on Windows. (perhaps when running
|
||||||
|
// all.bat?)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
|
||||||
|
|
||||||
|
procbind = modws2_32.NewProc("bind")
|
||||||
|
procgetpeername = modws2_32.NewProc("getpeername")
|
||||||
|
procgetsockname = modws2_32.NewProc("getsockname")
|
||||||
|
)
|
||||||
|
|
||||||
|
func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
||||||
|
if r1 == socketError {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
|
||||||
|
if r1 == socketError {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
|
||||||
|
if r1 == socketError {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
124
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
124
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package winio
|
package winio
|
||||||
@ -13,6 +14,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
|
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
|
||||||
@ -21,10 +24,10 @@ import (
|
|||||||
//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
|
//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 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 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 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 rtlNtStatusToDosError(status ntStatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||||
//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U
|
//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) = ntdll.RtlDosPathNameToNtPathName_U
|
||||||
//sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl
|
//sys rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) = ntdll.RtlDefaultNpAcl
|
||||||
|
|
||||||
type ioStatusBlock struct {
|
type ioStatusBlock struct {
|
||||||
Status, Information uintptr
|
Status, Information uintptr
|
||||||
@ -51,45 +54,22 @@ type securityDescriptor struct {
|
|||||||
Control uint16
|
Control uint16
|
||||||
Owner uintptr
|
Owner uintptr
|
||||||
Group uintptr
|
Group uintptr
|
||||||
Sacl uintptr
|
Sacl uintptr //revive:disable-line:var-naming SACL, not Sacl
|
||||||
Dacl uintptr
|
Dacl uintptr //revive:disable-line:var-naming DACL, not Dacl
|
||||||
}
|
}
|
||||||
|
|
||||||
type ntstatus int32
|
type ntStatus int32
|
||||||
|
|
||||||
func (status ntstatus) Err() error {
|
func (status ntStatus) Err() error {
|
||||||
if status >= 0 {
|
if status >= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return rtlNtStatusToDosError(status)
|
return rtlNtStatusToDosError(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
cERROR_PIPE_BUSY = syscall.Errno(231)
|
|
||||||
cERROR_NO_DATA = syscall.Errno(232)
|
|
||||||
cERROR_PIPE_CONNECTED = syscall.Errno(535)
|
|
||||||
cERROR_SEM_TIMEOUT = syscall.Errno(121)
|
|
||||||
|
|
||||||
cSECURITY_SQOS_PRESENT = 0x100000
|
|
||||||
cSECURITY_ANONYMOUS = 0
|
|
||||||
|
|
||||||
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 (
|
var (
|
||||||
// ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed.
|
// ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed.
|
||||||
// This error should match net.errClosing since docker takes a dependency on its text.
|
ErrPipeListenerClosed = net.ErrClosed
|
||||||
ErrPipeListenerClosed = errors.New("use of closed network connection")
|
|
||||||
|
|
||||||
errPipeWriteClosed = errors.New("pipe has been closed for write")
|
errPipeWriteClosed = errors.New("pipe has been closed for write")
|
||||||
)
|
)
|
||||||
@ -116,9 +96,10 @@ func (f *win32Pipe) RemoteAddr() net.Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *win32Pipe) SetDeadline(t time.Time) error {
|
func (f *win32Pipe) SetDeadline(t time.Time) error {
|
||||||
f.SetReadDeadline(t)
|
if err := f.SetReadDeadline(t); err != nil {
|
||||||
f.SetWriteDeadline(t)
|
return err
|
||||||
return nil
|
}
|
||||||
|
return f.SetWriteDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloseWrite closes the write side of a message pipe in byte mode.
|
// CloseWrite closes the write side of a message pipe in byte mode.
|
||||||
@ -157,14 +138,14 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
|
|||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
n, err := f.win32File.Read(b)
|
n, err := f.win32File.Read(b)
|
||||||
if err == io.EOF {
|
if err == io.EOF { //nolint:errorlint
|
||||||
// If this was the result of a zero-byte read, then
|
// If this was the result of a zero-byte read, then
|
||||||
// it is possible that the read was due to a zero-size
|
// it is possible that the read was due to a zero-size
|
||||||
// message. Since we are simulating CloseWrite with a
|
// message. Since we are simulating CloseWrite with a
|
||||||
// zero-byte message, ensure that all future Read() calls
|
// zero-byte message, ensure that all future Read() calls
|
||||||
// also return EOF.
|
// also return EOF.
|
||||||
f.readEOF = true
|
f.readEOF = true
|
||||||
} else if err == syscall.ERROR_MORE_DATA {
|
} else if err == syscall.ERROR_MORE_DATA { //nolint:errorlint // err is Errno
|
||||||
// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
|
// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
|
||||||
// and the message still has more bytes. Treat this as a success, since
|
// and the message still has more bytes. Treat this as a success, since
|
||||||
// this package presents all named pipes as byte streams.
|
// this package presents all named pipes as byte streams.
|
||||||
@ -173,7 +154,7 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
|
|||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s pipeAddress) Network() string {
|
func (pipeAddress) Network() string {
|
||||||
return "pipe"
|
return "pipe"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,16 +165,21 @@ func (s pipeAddress) String() string {
|
|||||||
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
|
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
|
||||||
func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) {
|
func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) {
|
||||||
for {
|
for {
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return syscall.Handle(0), ctx.Err()
|
return syscall.Handle(0), ctx.Err()
|
||||||
default:
|
default:
|
||||||
h, err := createFile(*path, access, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
|
h, err := createFile(*path,
|
||||||
|
access,
|
||||||
|
0,
|
||||||
|
nil,
|
||||||
|
syscall.OPEN_EXISTING,
|
||||||
|
windows.FILE_FLAG_OVERLAPPED|windows.SECURITY_SQOS_PRESENT|windows.SECURITY_ANONYMOUS,
|
||||||
|
0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return h, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
if err != cERROR_PIPE_BUSY {
|
if err != windows.ERROR_PIPE_BUSY { //nolint:errorlint // err is Errno
|
||||||
return h, &os.PathError{Err: err, Op: "open", Path: *path}
|
return h, &os.PathError{Err: err, Op: "open", Path: *path}
|
||||||
}
|
}
|
||||||
// Wait 10 msec and try again. This is a rather simplistic
|
// Wait 10 msec and try again. This is a rather simplistic
|
||||||
@ -213,9 +199,10 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
|
|||||||
} else {
|
} else {
|
||||||
absTimeout = time.Now().Add(2 * time.Second)
|
absTimeout = time.Now().Add(2 * time.Second)
|
||||||
}
|
}
|
||||||
ctx, _ := context.WithDeadline(context.Background(), absTimeout)
|
ctx, cancel := context.WithDeadline(context.Background(), absTimeout)
|
||||||
|
defer cancel()
|
||||||
conn, err := DialPipeContext(ctx, path)
|
conn, err := DialPipeContext(ctx, path)
|
||||||
if err == context.DeadlineExceeded {
|
if errors.Is(err, context.DeadlineExceeded) {
|
||||||
return nil, ErrTimeout
|
return nil, ErrTimeout
|
||||||
}
|
}
|
||||||
return conn, err
|
return conn, err
|
||||||
@ -251,7 +238,7 @@ func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn,
|
|||||||
|
|
||||||
// If the pipe is in message mode, return a message byte pipe, which
|
// If the pipe is in message mode, return a message byte pipe, which
|
||||||
// supports CloseWrite().
|
// supports CloseWrite().
|
||||||
if flags&cPIPE_TYPE_MESSAGE != 0 {
|
if flags&windows.PIPE_TYPE_MESSAGE != 0 {
|
||||||
return &win32MessageBytePipe{
|
return &win32MessageBytePipe{
|
||||||
win32Pipe: win32Pipe{win32File: f, path: path},
|
win32Pipe: win32Pipe{win32File: f, path: path},
|
||||||
}, nil
|
}, nil
|
||||||
@ -283,7 +270,11 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
|||||||
oa.Length = unsafe.Sizeof(oa)
|
oa.Length = unsafe.Sizeof(oa)
|
||||||
|
|
||||||
var ntPath unicodeString
|
var ntPath unicodeString
|
||||||
if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil {
|
if err := rtlDosPathNameToNtPathName(&path16[0],
|
||||||
|
&ntPath,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
).Err(); err != nil {
|
||||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||||
}
|
}
|
||||||
defer localFree(ntPath.Buffer)
|
defer localFree(ntPath.Buffer)
|
||||||
@ -292,8 +283,8 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
|||||||
// The security descriptor is only needed for the first pipe.
|
// The security descriptor is only needed for the first pipe.
|
||||||
if first {
|
if first {
|
||||||
if sd != nil {
|
if sd != nil {
|
||||||
len := uint32(len(sd))
|
l := uint32(len(sd))
|
||||||
sdb := localAlloc(0, len)
|
sdb := localAlloc(0, l)
|
||||||
defer localFree(sdb)
|
defer localFree(sdb)
|
||||||
copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
|
copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
|
||||||
oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
|
oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
|
||||||
@ -301,28 +292,28 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
|||||||
// Construct the default named pipe security descriptor.
|
// Construct the default named pipe security descriptor.
|
||||||
var dacl uintptr
|
var dacl uintptr
|
||||||
if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
|
if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
|
||||||
return 0, fmt.Errorf("getting default named pipe ACL: %s", err)
|
return 0, fmt.Errorf("getting default named pipe ACL: %w", err)
|
||||||
}
|
}
|
||||||
defer localFree(dacl)
|
defer localFree(dacl)
|
||||||
|
|
||||||
sdb := &securityDescriptor{
|
sdb := &securityDescriptor{
|
||||||
Revision: 1,
|
Revision: 1,
|
||||||
Control: cSE_DACL_PRESENT,
|
Control: windows.SE_DACL_PRESENT,
|
||||||
Dacl: dacl,
|
Dacl: dacl,
|
||||||
}
|
}
|
||||||
oa.SecurityDescriptor = sdb
|
oa.SecurityDescriptor = sdb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS)
|
typ := uint32(windows.FILE_PIPE_REJECT_REMOTE_CLIENTS)
|
||||||
if c.MessageMode {
|
if c.MessageMode {
|
||||||
typ |= cFILE_PIPE_MESSAGE_TYPE
|
typ |= windows.FILE_PIPE_MESSAGE_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
disposition := uint32(cFILE_OPEN)
|
disposition := uint32(windows.FILE_OPEN)
|
||||||
access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
|
access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
|
||||||
if first {
|
if first {
|
||||||
disposition = cFILE_CREATE
|
disposition = windows.FILE_CREATE
|
||||||
// By not asking for read or write access, the named pipe file system
|
// By not asking for read or write access, the named pipe file system
|
||||||
// will put this pipe into an initially disconnected state, blocking
|
// will put this pipe into an initially disconnected state, blocking
|
||||||
// client connections until the next call with first == false.
|
// client connections until the next call with first == false.
|
||||||
@ -335,7 +326,20 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
|||||||
h syscall.Handle
|
h syscall.Handle
|
||||||
iosb ioStatusBlock
|
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()
|
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 {
|
if err != nil {
|
||||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||||
}
|
}
|
||||||
@ -380,7 +384,7 @@ func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) {
|
|||||||
p.Close()
|
p.Close()
|
||||||
p = nil
|
p = nil
|
||||||
err = <-ch
|
err = <-ch
|
||||||
if err == nil || err == ErrFileClosed {
|
if err == nil || err == ErrFileClosed { //nolint:errorlint // err is Errno
|
||||||
err = ErrPipeListenerClosed
|
err = ErrPipeListenerClosed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,12 +406,12 @@ func (l *win32PipeListener) listenerRoutine() {
|
|||||||
p, err = l.makeConnectedServerPipe()
|
p, err = l.makeConnectedServerPipe()
|
||||||
// If the connection was immediately closed by the client, try
|
// If the connection was immediately closed by the client, try
|
||||||
// again.
|
// again.
|
||||||
if err != cERROR_NO_DATA {
|
if err != windows.ERROR_NO_DATA { //nolint:errorlint // err is Errno
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
responseCh <- acceptResponse{p, err}
|
responseCh <- acceptResponse{p, err}
|
||||||
closed = err == ErrPipeListenerClosed
|
closed = err == ErrPipeListenerClosed //nolint:errorlint // err is Errno
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
syscall.Close(l.firstHandle)
|
syscall.Close(l.firstHandle)
|
||||||
@ -469,15 +473,15 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func connectPipe(p *win32File) error {
|
func connectPipe(p *win32File) error {
|
||||||
c, err := p.prepareIo()
|
c, err := p.prepareIO()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer p.wg.Done()
|
defer p.wg.Done()
|
||||||
|
|
||||||
err = connectNamedPipe(p.handle, &c.o)
|
err = connectNamedPipe(p.handle, &c.o)
|
||||||
_, err = p.asyncIo(c, nil, 0, err)
|
_, err = p.asyncIO(c, nil, 0, err)
|
||||||
if err != nil && err != cERROR_PIPE_CONNECTED {
|
if err != nil && err != windows.ERROR_PIPE_CONNECTED { //nolint:errorlint // err is Errno
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
8
vendor/github.com/Microsoft/go-winio/pkg/etw/doc.go
generated
vendored
Normal file
8
vendor/github.com/Microsoft/go-winio/pkg/etw/doc.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Package etw provides support for TraceLogging-based ETW (Event Tracing
|
||||||
|
// for Windows). TraceLogging is a format of ETW events that are self-describing
|
||||||
|
// (the event contains information on its own schema). This allows them to be
|
||||||
|
// decoded without needing a separate manifest with event information. The
|
||||||
|
// implementation here is based on the information found in
|
||||||
|
// TraceLoggingProvider.h in the Windows SDK, which implements TraceLogging as a
|
||||||
|
// set of C macros.
|
||||||
|
package etw
|
27
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdata.go
generated
vendored
27
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdata.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
@ -14,60 +15,60 @@ type eventData struct {
|
|||||||
buffer bytes.Buffer
|
buffer bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
// bytes returns the raw binary data containing the event data. The returned
|
// toBytes returns the raw binary data containing the event data. The returned
|
||||||
// value is not copied from the internal buffer, so it can be mutated by the
|
// value is not copied from the internal buffer, so it can be mutated by the
|
||||||
// eventData object after it is returned.
|
// eventData object after it is returned.
|
||||||
func (ed *eventData) bytes() []byte {
|
func (ed *eventData) toBytes() []byte {
|
||||||
return ed.buffer.Bytes()
|
return ed.buffer.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeString appends a string, including the null terminator, to the buffer.
|
// writeString appends a string, including the null terminator, to the buffer.
|
||||||
func (ed *eventData) writeString(data string) {
|
func (ed *eventData) writeString(data string) {
|
||||||
ed.buffer.WriteString(data)
|
_, _ = ed.buffer.WriteString(data)
|
||||||
ed.buffer.WriteByte(0)
|
_ = ed.buffer.WriteByte(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeInt8 appends a int8 to the buffer.
|
// writeInt8 appends a int8 to the buffer.
|
||||||
func (ed *eventData) writeInt8(value int8) {
|
func (ed *eventData) writeInt8(value int8) {
|
||||||
ed.buffer.WriteByte(uint8(value))
|
_ = ed.buffer.WriteByte(uint8(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeInt16 appends a int16 to the buffer.
|
// writeInt16 appends a int16 to the buffer.
|
||||||
func (ed *eventData) writeInt16(value int16) {
|
func (ed *eventData) writeInt16(value int16) {
|
||||||
binary.Write(&ed.buffer, binary.LittleEndian, value)
|
_ = binary.Write(&ed.buffer, binary.LittleEndian, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeInt32 appends a int32 to the buffer.
|
// writeInt32 appends a int32 to the buffer.
|
||||||
func (ed *eventData) writeInt32(value int32) {
|
func (ed *eventData) writeInt32(value int32) {
|
||||||
binary.Write(&ed.buffer, binary.LittleEndian, value)
|
_ = binary.Write(&ed.buffer, binary.LittleEndian, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeInt64 appends a int64 to the buffer.
|
// writeInt64 appends a int64 to the buffer.
|
||||||
func (ed *eventData) writeInt64(value int64) {
|
func (ed *eventData) writeInt64(value int64) {
|
||||||
binary.Write(&ed.buffer, binary.LittleEndian, value)
|
_ = binary.Write(&ed.buffer, binary.LittleEndian, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeUint8 appends a uint8 to the buffer.
|
// writeUint8 appends a uint8 to the buffer.
|
||||||
func (ed *eventData) writeUint8(value uint8) {
|
func (ed *eventData) writeUint8(value uint8) {
|
||||||
ed.buffer.WriteByte(value)
|
_ = ed.buffer.WriteByte(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeUint16 appends a uint16 to the buffer.
|
// writeUint16 appends a uint16 to the buffer.
|
||||||
func (ed *eventData) writeUint16(value uint16) {
|
func (ed *eventData) writeUint16(value uint16) {
|
||||||
binary.Write(&ed.buffer, binary.LittleEndian, value)
|
_ = binary.Write(&ed.buffer, binary.LittleEndian, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeUint32 appends a uint32 to the buffer.
|
// writeUint32 appends a uint32 to the buffer.
|
||||||
func (ed *eventData) writeUint32(value uint32) {
|
func (ed *eventData) writeUint32(value uint32) {
|
||||||
binary.Write(&ed.buffer, binary.LittleEndian, value)
|
_ = binary.Write(&ed.buffer, binary.LittleEndian, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeUint64 appends a uint64 to the buffer.
|
// writeUint64 appends a uint64 to the buffer.
|
||||||
func (ed *eventData) writeUint64(value uint64) {
|
func (ed *eventData) writeUint64(value uint64) {
|
||||||
binary.Write(&ed.buffer, binary.LittleEndian, value)
|
_ = binary.Write(&ed.buffer, binary.LittleEndian, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeFiletime appends a FILETIME to the buffer.
|
// writeFiletime appends a FILETIME to the buffer.
|
||||||
func (ed *eventData) writeFiletime(value syscall.Filetime) {
|
func (ed *eventData) writeFiletime(value syscall.Filetime) {
|
||||||
binary.Write(&ed.buffer, binary.LittleEndian, value)
|
_ = binary.Write(&ed.buffer, binary.LittleEndian, value)
|
||||||
}
|
}
|
||||||
|
12
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdatadescriptor.go
generated
vendored
12
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdatadescriptor.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -13,11 +15,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type eventDataDescriptor struct {
|
type eventDataDescriptor struct {
|
||||||
ptr ptr64
|
ptr ptr64
|
||||||
size uint32
|
size uint32
|
||||||
dataType eventDataDescriptorType
|
dataType eventDataDescriptorType
|
||||||
reserved1 uint8
|
_ uint8
|
||||||
reserved2 uint16
|
_ uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEventDataDescriptor(dataType eventDataDescriptorType, buffer []byte) eventDataDescriptor {
|
func newEventDataDescriptor(dataType eventDataDescriptorType, buffer []byte) eventDataDescriptor {
|
||||||
|
8
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdescriptor.go
generated
vendored
8
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdescriptor.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
|
|
||||||
// Channel represents the ETW logging channel that is used. It can be used by
|
// Channel represents the ETW logging channel that is used. It can be used by
|
||||||
@ -45,6 +47,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// EventDescriptor represents various metadata for an ETW event.
|
// EventDescriptor represents various metadata for an ETW event.
|
||||||
|
//
|
||||||
|
//nolint:structcheck // task is currently unused
|
||||||
type eventDescriptor struct {
|
type eventDescriptor struct {
|
||||||
id uint16
|
id uint16
|
||||||
version uint8
|
version uint8
|
||||||
@ -70,6 +74,8 @@ func newEventDescriptor() *eventDescriptor {
|
|||||||
// should uniquely identify the other event metadata (contained in
|
// should uniquely identify the other event metadata (contained in
|
||||||
// EventDescriptor, and field metadata). Only the lower 24 bits of this value
|
// EventDescriptor, and field metadata). Only the lower 24 bits of this value
|
||||||
// are relevant.
|
// are relevant.
|
||||||
|
//
|
||||||
|
//nolint:unused // keep for future use
|
||||||
func (ed *eventDescriptor) identity() uint32 {
|
func (ed *eventDescriptor) identity() uint32 {
|
||||||
return (uint32(ed.version) << 16) | uint32(ed.id)
|
return (uint32(ed.version) << 16) | uint32(ed.id)
|
||||||
}
|
}
|
||||||
@ -78,6 +84,8 @@ func (ed *eventDescriptor) identity() uint32 {
|
|||||||
// should uniquely identify the other event metadata (contained in
|
// should uniquely identify the other event metadata (contained in
|
||||||
// EventDescriptor, and field metadata). Only the lower 24 bits of this value
|
// EventDescriptor, and field metadata). Only the lower 24 bits of this value
|
||||||
// are relevant.
|
// are relevant.
|
||||||
|
//
|
||||||
|
//nolint:unused // keep for future use
|
||||||
func (ed *eventDescriptor) setIdentity(identity uint32) {
|
func (ed *eventDescriptor) setIdentity(identity uint32) {
|
||||||
ed.id = uint16(identity)
|
ed.id = uint16(identity)
|
||||||
ed.version = uint8(identity >> 16)
|
ed.version = uint8(identity >> 16)
|
||||||
|
22
vendor/github.com/Microsoft/go-winio/pkg/etw/eventmetadata.go
generated
vendored
22
vendor/github.com/Microsoft/go-winio/pkg/etw/eventmetadata.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -10,6 +12,8 @@ type inType byte
|
|||||||
|
|
||||||
// Various inType definitions for TraceLogging. These must match the definitions
|
// Various inType definitions for TraceLogging. These must match the definitions
|
||||||
// found in TraceLoggingProvider.h in the Windows SDK.
|
// found in TraceLoggingProvider.h in the Windows SDK.
|
||||||
|
//
|
||||||
|
//nolint:deadcode,varcheck // keep unused constants for potential future use
|
||||||
const (
|
const (
|
||||||
inTypeNull inType = iota
|
inTypeNull inType = iota
|
||||||
inTypeUnicodeString
|
inTypeUnicodeString
|
||||||
@ -47,6 +51,8 @@ type outType byte
|
|||||||
|
|
||||||
// Various outType definitions for TraceLogging. These must match the
|
// Various outType definitions for TraceLogging. These must match the
|
||||||
// definitions found in TraceLoggingProvider.h in the Windows SDK.
|
// definitions found in TraceLoggingProvider.h in the Windows SDK.
|
||||||
|
//
|
||||||
|
//nolint:deadcode,varcheck // keep unused constants for potential future use
|
||||||
const (
|
const (
|
||||||
// outTypeDefault indicates that the default formatting for the inType will
|
// outTypeDefault indicates that the default formatting for the inType will
|
||||||
// be used by the event decoder.
|
// be used by the event decoder.
|
||||||
@ -81,11 +87,11 @@ type eventMetadata struct {
|
|||||||
buffer bytes.Buffer
|
buffer bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
// bytes returns the raw binary data containing the event metadata. Before being
|
// toBytes returns the raw binary data containing the event metadata. Before being
|
||||||
// returned, the current size of the buffer is written to the start of the
|
// returned, the current size of the buffer is written to the start of the
|
||||||
// buffer. The returned value is not copied from the internal buffer, so it can
|
// buffer. The returned value is not copied from the internal buffer, so it can
|
||||||
// be mutated by the eventMetadata object after it is returned.
|
// be mutated by the eventMetadata object after it is returned.
|
||||||
func (em *eventMetadata) bytes() []byte {
|
func (em *eventMetadata) toBytes() []byte {
|
||||||
// Finalize the event metadata buffer by filling in the buffer length at the
|
// Finalize the event metadata buffer by filling in the buffer length at the
|
||||||
// beginning.
|
// beginning.
|
||||||
binary.LittleEndian.PutUint16(em.buffer.Bytes(), uint16(em.buffer.Len()))
|
binary.LittleEndian.PutUint16(em.buffer.Bytes(), uint16(em.buffer.Len()))
|
||||||
@ -95,7 +101,7 @@ func (em *eventMetadata) bytes() []byte {
|
|||||||
// writeEventHeader writes the metadata for the start of an event to the buffer.
|
// writeEventHeader writes the metadata for the start of an event to the buffer.
|
||||||
// This specifies the event name and tags.
|
// This specifies the event name and tags.
|
||||||
func (em *eventMetadata) writeEventHeader(name string, tags uint32) {
|
func (em *eventMetadata) writeEventHeader(name string, tags uint32) {
|
||||||
binary.Write(&em.buffer, binary.LittleEndian, uint16(0)) // Length placeholder
|
_ = binary.Write(&em.buffer, binary.LittleEndian, uint16(0)) // Length placeholder
|
||||||
em.writeTags(tags)
|
em.writeTags(tags)
|
||||||
em.buffer.WriteString(name)
|
em.buffer.WriteString(name)
|
||||||
em.buffer.WriteByte(0) // Null terminator for name
|
em.buffer.WriteByte(0) // Null terminator for name
|
||||||
@ -118,7 +124,7 @@ func (em *eventMetadata) writeFieldInner(name string, inType inType, outType out
|
|||||||
}
|
}
|
||||||
|
|
||||||
if arrSize != 0 {
|
if arrSize != 0 {
|
||||||
binary.Write(&em.buffer, binary.LittleEndian, arrSize)
|
_ = binary.Write(&em.buffer, binary.LittleEndian, arrSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,13 +157,17 @@ func (em *eventMetadata) writeTags(tags uint32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeField writes the metadata for a simple field to the buffer.
|
// writeField writes the metadata for a simple field to the buffer.
|
||||||
|
//
|
||||||
|
//nolint:unparam // tags is currently always 0, may change in the future
|
||||||
func (em *eventMetadata) writeField(name string, inType inType, outType outType, tags uint32) {
|
func (em *eventMetadata) writeField(name string, inType inType, outType outType, tags uint32) {
|
||||||
em.writeFieldInner(name, inType, outType, tags, 0)
|
em.writeFieldInner(name, inType, outType, tags, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeArray writes the metadata for an array field to the buffer. The number
|
// writeArray writes the metadata for an array field to the buffer. The number
|
||||||
// of elements in the array must be written as a uint16 in the event data,
|
// of elements in the array must be written as a uint16 in the event data,
|
||||||
// immediately preceeding the event data.
|
// immediately preceding the event data.
|
||||||
|
//
|
||||||
|
//nolint:unparam // tags is currently always 0, may change in the future
|
||||||
func (em *eventMetadata) writeArray(name string, inType inType, outType outType, tags uint32) {
|
func (em *eventMetadata) writeArray(name string, inType inType, outType outType, tags uint32) {
|
||||||
em.writeFieldInner(name, inType|inTypeArray, outType, tags, 0)
|
em.writeFieldInner(name, inType|inTypeArray, outType, tags, 0)
|
||||||
}
|
}
|
||||||
@ -165,6 +175,8 @@ func (em *eventMetadata) writeArray(name string, inType inType, outType outType,
|
|||||||
// writeCountedArray writes the metadata for an array field to the buffer. The
|
// writeCountedArray writes the metadata for an array field to the buffer. The
|
||||||
// size of a counted array is fixed, and the size is written into the metadata
|
// size of a counted array is fixed, and the size is written into the metadata
|
||||||
// directly.
|
// directly.
|
||||||
|
//
|
||||||
|
//nolint:unused // keep for future use
|
||||||
func (em *eventMetadata) writeCountedArray(name string, count uint16, inType inType, outType outType, tags uint32) {
|
func (em *eventMetadata) writeCountedArray(name string, count uint16, inType inType, outType outType, tags uint32) {
|
||||||
em.writeFieldInner(name, inType|inTypeCountedArray, outType, tags, count)
|
em.writeFieldInner(name, inType|inTypeCountedArray, outType, tags, count)
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/Microsoft/go-winio/pkg/etw/eventopt.go
generated
vendored
1
vendor/github.com/Microsoft/go-winio/pkg/etw/eventopt.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
|
10
vendor/github.com/Microsoft/go-winio/pkg/etw/fieldopt.go
generated
vendored
10
vendor/github.com/Microsoft/go-winio/pkg/etw/fieldopt.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
@ -481,7 +482,7 @@ func SmartField(name string, v interface{}) FieldOpt {
|
|||||||
case reflect.Int32:
|
case reflect.Int32:
|
||||||
return SmartField(name, int32(rv.Int()))
|
return SmartField(name, int32(rv.Int()))
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
return SmartField(name, int64(rv.Int()))
|
return SmartField(name, int64(rv.Int())) //nolint:unconvert // make look consistent
|
||||||
case reflect.Uint:
|
case reflect.Uint:
|
||||||
return SmartField(name, uint(rv.Uint()))
|
return SmartField(name, uint(rv.Uint()))
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
@ -491,13 +492,13 @@ func SmartField(name string, v interface{}) FieldOpt {
|
|||||||
case reflect.Uint32:
|
case reflect.Uint32:
|
||||||
return SmartField(name, uint32(rv.Uint()))
|
return SmartField(name, uint32(rv.Uint()))
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
return SmartField(name, uint64(rv.Uint()))
|
return SmartField(name, uint64(rv.Uint())) //nolint:unconvert // make look consistent
|
||||||
case reflect.Uintptr:
|
case reflect.Uintptr:
|
||||||
return SmartField(name, uintptr(rv.Uint()))
|
return SmartField(name, uintptr(rv.Uint()))
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
return SmartField(name, float32(rv.Float()))
|
return SmartField(name, float32(rv.Float()))
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
return SmartField(name, float64(rv.Float()))
|
return SmartField(name, float64(rv.Float())) //nolint:unconvert // make look consistent
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return SmartField(name, rv.String())
|
return SmartField(name, rv.String())
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
@ -509,6 +510,9 @@ func SmartField(name string, v interface{}) FieldOpt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Struct(name, fields...)
|
return Struct(name, fields...)
|
||||||
|
case reflect.Array, reflect.Chan, reflect.Complex128, reflect.Complex64,
|
||||||
|
reflect.Func, reflect.Interface, reflect.Invalid, reflect.Map, reflect.Ptr,
|
||||||
|
reflect.Slice, reflect.UnsafePointer:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
vendor/github.com/Microsoft/go-winio/pkg/etw/newprovider.go
generated
vendored
15
vendor/github.com/Microsoft/go-winio/pkg/etw/newprovider.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows && (amd64 || arm64 || 386)
|
||||||
// +build windows
|
// +build windows
|
||||||
// +build amd64 arm64 386
|
// +build amd64 arm64 386
|
||||||
|
|
||||||
@ -45,18 +46,18 @@ func NewProviderWithOptions(name string, options ...ProviderOpt) (provider *Prov
|
|||||||
|
|
||||||
trait := &bytes.Buffer{}
|
trait := &bytes.Buffer{}
|
||||||
if opts.group != (guid.GUID{}) {
|
if opts.group != (guid.GUID{}) {
|
||||||
binary.Write(trait, binary.LittleEndian, uint16(0)) // Write empty size for buffer (update later)
|
_ = binary.Write(trait, binary.LittleEndian, uint16(0)) // Write empty size for buffer (update later)
|
||||||
binary.Write(trait, binary.LittleEndian, uint8(1)) // EtwProviderTraitTypeGroup
|
_ = binary.Write(trait, binary.LittleEndian, uint8(1)) // EtwProviderTraitTypeGroup
|
||||||
traitArray := opts.group.ToWindowsArray() // Append group guid
|
traitArray := opts.group.ToWindowsArray() // Append group guid
|
||||||
trait.Write(traitArray[:])
|
trait.Write(traitArray[:])
|
||||||
binary.LittleEndian.PutUint16(trait.Bytes(), uint16(trait.Len())) // Update size
|
binary.LittleEndian.PutUint16(trait.Bytes(), uint16(trait.Len())) // Update size
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata := &bytes.Buffer{}
|
metadata := &bytes.Buffer{}
|
||||||
binary.Write(metadata, binary.LittleEndian, uint16(0)) // Write empty size for buffer (to update later)
|
_ = binary.Write(metadata, binary.LittleEndian, uint16(0)) // Write empty size for buffer (to update later)
|
||||||
metadata.WriteString(name)
|
metadata.WriteString(name)
|
||||||
metadata.WriteByte(0) // Null terminator for name
|
metadata.WriteByte(0) // Null terminator for name
|
||||||
trait.WriteTo(metadata) // Add traits if applicable
|
_, _ = trait.WriteTo(metadata) // Add traits if applicable
|
||||||
binary.LittleEndian.PutUint16(metadata.Bytes(), uint16(metadata.Len())) // Update the size at the beginning of the buffer
|
binary.LittleEndian.PutUint16(metadata.Bytes(), uint16(metadata.Len())) // Update the size at the beginning of the buffer
|
||||||
provider.metadata = metadata.Bytes()
|
provider.metadata = metadata.Bytes()
|
||||||
|
|
||||||
@ -64,8 +65,8 @@ func NewProviderWithOptions(name string, options ...ProviderOpt) (provider *Prov
|
|||||||
provider.handle,
|
provider.handle,
|
||||||
eventInfoClassProviderSetTraits,
|
eventInfoClassProviderSetTraits,
|
||||||
uintptr(unsafe.Pointer(&provider.metadata[0])),
|
uintptr(unsafe.Pointer(&provider.metadata[0])),
|
||||||
uint32(len(provider.metadata))); err != nil {
|
uint32(len(provider.metadata)),
|
||||||
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
vendor/github.com/Microsoft/go-winio/pkg/etw/newprovider_unsupported.go
generated
vendored
4
vendor/github.com/Microsoft/go-winio/pkg/etw/newprovider_unsupported.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
// +build windows
|
//go:build windows && arm
|
||||||
// +build arm
|
// +build windows,arm
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
|
|
||||||
|
76
vendor/github.com/Microsoft/go-winio/pkg/etw/provider.go
generated
vendored
76
vendor/github.com/Microsoft/go-winio/pkg/etw/provider.go
generated
vendored
@ -1,9 +1,10 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1" //nolint:gosec // not used for secure application
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
@ -27,7 +28,7 @@ type Provider struct {
|
|||||||
keywordAll uint64
|
keywordAll uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the `provider`.ID as a string
|
// String returns the `provider`.ID as a string.
|
||||||
func (provider *Provider) String() string {
|
func (provider *Provider) String() string {
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
return "<nil>"
|
return "<nil>"
|
||||||
@ -54,6 +55,7 @@ const (
|
|||||||
|
|
||||||
type eventInfoClass uint32
|
type eventInfoClass uint32
|
||||||
|
|
||||||
|
//nolint:deadcode,varcheck // keep unused constants for potential future use
|
||||||
const (
|
const (
|
||||||
eventInfoClassProviderBinaryTrackInfo eventInfoClass = iota
|
eventInfoClassProviderBinaryTrackInfo eventInfoClass = iota
|
||||||
eventInfoClassProviderSetReserved1
|
eventInfoClassProviderSetReserved1
|
||||||
@ -65,10 +67,19 @@ const (
|
|||||||
// enable/disable notifications from ETW.
|
// enable/disable notifications from ETW.
|
||||||
type EnableCallback func(guid.GUID, ProviderState, Level, uint64, uint64, uintptr)
|
type EnableCallback func(guid.GUID, ProviderState, Level, uint64, uint64, uintptr)
|
||||||
|
|
||||||
func providerCallback(sourceID guid.GUID, state ProviderState, level Level, matchAnyKeyword uint64, matchAllKeyword uint64, filterData uintptr, i uintptr) {
|
func providerCallback(
|
||||||
|
sourceID guid.GUID,
|
||||||
|
state ProviderState,
|
||||||
|
level Level,
|
||||||
|
matchAnyKeyword uint64,
|
||||||
|
matchAllKeyword uint64,
|
||||||
|
filterData uintptr,
|
||||||
|
i uintptr,
|
||||||
|
) {
|
||||||
provider := providers.getProvider(uint(i))
|
provider := providers.getProvider(uint(i))
|
||||||
|
|
||||||
switch state {
|
switch state {
|
||||||
|
case ProviderStateCaptureState:
|
||||||
case ProviderStateDisable:
|
case ProviderStateDisable:
|
||||||
provider.enabled = false
|
provider.enabled = false
|
||||||
case ProviderStateEnable:
|
case ProviderStateEnable:
|
||||||
@ -90,17 +101,22 @@ func providerCallback(sourceID guid.GUID, state ProviderState, level Level, matc
|
|||||||
//
|
//
|
||||||
// The algorithm is roughly the RFC 4122 algorithm for a V5 UUID, but differs in
|
// The algorithm is roughly the RFC 4122 algorithm for a V5 UUID, but differs in
|
||||||
// the following ways:
|
// the following ways:
|
||||||
// - The input name is first upper-cased, UTF16-encoded, and converted to
|
// - The input name is first upper-cased, UTF16-encoded, and converted to
|
||||||
// big-endian.
|
// big-endian.
|
||||||
// - No variant is set on the result UUID.
|
// - No variant is set on the result UUID.
|
||||||
// - The result UUID is treated as being in little-endian format, rather than
|
// - The result UUID is treated as being in little-endian format, rather than
|
||||||
// big-endian.
|
// big-endian.
|
||||||
func providerIDFromName(name string) guid.GUID {
|
func providerIDFromName(name string) guid.GUID {
|
||||||
buffer := sha1.New()
|
buffer := sha1.New() //nolint:gosec // not used for secure application
|
||||||
namespace := guid.GUID{0x482C2DB2, 0xC390, 0x47C8, [8]byte{0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB}}
|
namespace := guid.GUID{
|
||||||
|
Data1: 0x482C2DB2,
|
||||||
|
Data2: 0xC390,
|
||||||
|
Data3: 0x47C8,
|
||||||
|
Data4: [8]byte{0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB},
|
||||||
|
}
|
||||||
namespaceBytes := namespace.ToArray()
|
namespaceBytes := namespace.ToArray()
|
||||||
buffer.Write(namespaceBytes[:])
|
buffer.Write(namespaceBytes[:])
|
||||||
binary.Write(buffer, binary.BigEndian, utf16.Encode([]rune(strings.ToUpper(name))))
|
_ = binary.Write(buffer, binary.BigEndian, utf16.Encode([]rune(strings.ToUpper(name))))
|
||||||
|
|
||||||
sum := buffer.Sum(nil)
|
sum := buffer.Sum(nil)
|
||||||
sum[7] = (sum[7] & 0xf) | 0x50
|
sum[7] = (sum[7] & 0xf) | 0x50
|
||||||
@ -117,25 +133,24 @@ type providerOpts struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ProviderOpt allows the caller to specify provider options to
|
// ProviderOpt allows the caller to specify provider options to
|
||||||
// NewProviderWithOptions
|
// NewProviderWithOptions.
|
||||||
type ProviderOpt func(*providerOpts)
|
type ProviderOpt func(*providerOpts)
|
||||||
|
|
||||||
// WithCallback is used to provide a callback option to NewProviderWithOptions
|
// WithCallback is used to provide a callback option to NewProviderWithOptions.
|
||||||
func WithCallback(callback EnableCallback) ProviderOpt {
|
func WithCallback(callback EnableCallback) ProviderOpt {
|
||||||
return func(opts *providerOpts) {
|
return func(opts *providerOpts) {
|
||||||
opts.callback = callback
|
opts.callback = callback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithID is used to provide a provider ID option to NewProviderWithOptions
|
// WithID is used to provide a provider ID option to NewProviderWithOptions.
|
||||||
func WithID(id guid.GUID) ProviderOpt {
|
func WithID(id guid.GUID) ProviderOpt {
|
||||||
return func(opts *providerOpts) {
|
return func(opts *providerOpts) {
|
||||||
opts.id = id
|
opts.id = id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithGroup is used to provide a provider group option to
|
// WithGroup is used to provide a provider group option to NewProviderWithOptions.
|
||||||
// NewProviderWithOptions
|
|
||||||
func WithGroup(group guid.GUID) ProviderOpt {
|
func WithGroup(group guid.GUID) ProviderOpt {
|
||||||
return func(opts *providerOpts) {
|
return func(opts *providerOpts) {
|
||||||
opts.group = group
|
opts.group = group
|
||||||
@ -237,11 +252,17 @@ func (provider *Provider) WriteEvent(name string, eventOpts []EventOpt, fieldOpt
|
|||||||
// event metadata (e.g. for the name) so we don't need to do this check for
|
// event metadata (e.g. for the name) so we don't need to do this check for
|
||||||
// the metadata.
|
// the metadata.
|
||||||
dataBlobs := [][]byte{}
|
dataBlobs := [][]byte{}
|
||||||
if len(ed.bytes()) > 0 {
|
if len(ed.toBytes()) > 0 {
|
||||||
dataBlobs = [][]byte{ed.bytes()}
|
dataBlobs = [][]byte{ed.toBytes()}
|
||||||
}
|
}
|
||||||
|
|
||||||
return provider.writeEventRaw(options.descriptor, options.activityID, options.relatedActivityID, [][]byte{em.bytes()}, dataBlobs)
|
return provider.writeEventRaw(
|
||||||
|
options.descriptor,
|
||||||
|
options.activityID,
|
||||||
|
options.relatedActivityID,
|
||||||
|
[][]byte{em.toBytes()},
|
||||||
|
dataBlobs,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeEventRaw writes a single ETW event from the provider. This function is
|
// writeEventRaw writes a single ETW event from the provider. This function is
|
||||||
@ -257,17 +278,24 @@ func (provider *Provider) writeEventRaw(
|
|||||||
relatedActivityID guid.GUID,
|
relatedActivityID guid.GUID,
|
||||||
metadataBlobs [][]byte,
|
metadataBlobs [][]byte,
|
||||||
dataBlobs [][]byte) error {
|
dataBlobs [][]byte) error {
|
||||||
|
|
||||||
dataDescriptorCount := uint32(1 + len(metadataBlobs) + len(dataBlobs))
|
dataDescriptorCount := uint32(1 + len(metadataBlobs) + len(dataBlobs))
|
||||||
dataDescriptors := make([]eventDataDescriptor, 0, dataDescriptorCount)
|
dataDescriptors := make([]eventDataDescriptor, 0, dataDescriptorCount)
|
||||||
|
|
||||||
dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeProviderMetadata, provider.metadata))
|
dataDescriptors = append(dataDescriptors,
|
||||||
|
newEventDataDescriptor(eventDataDescriptorTypeProviderMetadata, provider.metadata))
|
||||||
for _, blob := range metadataBlobs {
|
for _, blob := range metadataBlobs {
|
||||||
dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeEventMetadata, blob))
|
dataDescriptors = append(dataDescriptors,
|
||||||
|
newEventDataDescriptor(eventDataDescriptorTypeEventMetadata, blob))
|
||||||
}
|
}
|
||||||
for _, blob := range dataBlobs {
|
for _, blob := range dataBlobs {
|
||||||
dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeUserData, blob))
|
dataDescriptors = append(dataDescriptors,
|
||||||
|
newEventDataDescriptor(eventDataDescriptorTypeUserData, blob))
|
||||||
}
|
}
|
||||||
|
|
||||||
return eventWriteTransfer(provider.handle, descriptor, (*windows.GUID)(&activityID), (*windows.GUID)(&relatedActivityID), dataDescriptorCount, &dataDescriptors[0])
|
return eventWriteTransfer(provider.handle,
|
||||||
|
descriptor,
|
||||||
|
(*windows.GUID)(&activityID),
|
||||||
|
(*windows.GUID)(&relatedActivityID),
|
||||||
|
dataDescriptorCount,
|
||||||
|
&dataDescriptors[0])
|
||||||
}
|
}
|
||||||
|
4
vendor/github.com/Microsoft/go-winio/pkg/etw/providerglobal.go
generated
vendored
4
vendor/github.com/Microsoft/go-winio/pkg/etw/providerglobal.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
@ -14,7 +15,6 @@ type providerMap struct {
|
|||||||
m map[uint]*Provider
|
m map[uint]*Provider
|
||||||
i uint
|
i uint
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
once sync.Once
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var providers = providerMap{
|
var providers = providerMap{
|
||||||
@ -50,5 +50,7 @@ func (p *providerMap) getProvider(index uint) *Provider {
|
|||||||
return p.m[index]
|
return p.m[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//todo: combine these into struct, so that "globalProviderCallback" is guaranteed to be initialized through method access
|
||||||
|
|
||||||
var providerCallbackOnce sync.Once
|
var providerCallbackOnce sync.Once
|
||||||
var globalProviderCallback uintptr
|
var globalProviderCallback uintptr
|
||||||
|
2
vendor/github.com/Microsoft/go-winio/pkg/etw/ptr64_32.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/pkg/etw/ptr64_32.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
//go:build windows && (386 || arm)
|
||||||
|
// +build windows
|
||||||
// +build 386 arm
|
// +build 386 arm
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
|
2
vendor/github.com/Microsoft/go-winio/pkg/etw/ptr64_64.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/pkg/etw/ptr64_64.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
//go:build windows && (amd64 || arm64)
|
||||||
|
// +build windows
|
||||||
// +build amd64 arm64
|
// +build amd64 arm64
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
// Package etw provides support for TraceLogging-based ETW (Event Tracing
|
//go:build windows
|
||||||
// for Windows). TraceLogging is a format of ETW events that are self-describing
|
|
||||||
// (the event contains information on its own schema). This allows them to be
|
|
||||||
// decoded without needing a separate manifest with event information. The
|
|
||||||
// implementation here is based on the information found in
|
|
||||||
// TraceLoggingProvider.h in the Windows SDK, which implements TraceLogging as a
|
|
||||||
// set of C macros.
|
|
||||||
package etw
|
package etw
|
||||||
|
|
||||||
//go:generate go run mksyscall_windows.go -output zsyscall_windows.go etw.go
|
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go syscall.go
|
||||||
|
|
||||||
//sys eventRegister(providerId *windows.GUID, callback uintptr, callbackContext uintptr, providerHandle *providerHandle) (win32err error) = advapi32.EventRegister
|
//sys eventRegister(providerId *windows.GUID, callback uintptr, callbackContext uintptr, providerHandle *providerHandle) (win32err error) = advapi32.EventRegister
|
||||||
|
|
1
vendor/github.com/Microsoft/go-winio/pkg/etw/wrapper_32.go
generated
vendored
1
vendor/github.com/Microsoft/go-winio/pkg/etw/wrapper_32.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows && (386 || arm)
|
||||||
// +build windows
|
// +build windows
|
||||||
// +build 386 arm
|
// +build 386 arm
|
||||||
|
|
||||||
|
21
vendor/github.com/Microsoft/go-winio/pkg/etw/wrapper_64.go
generated
vendored
21
vendor/github.com/Microsoft/go-winio/pkg/etw/wrapper_64.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows && (amd64 || arm64)
|
||||||
// +build windows
|
// +build windows
|
||||||
// +build amd64 arm64
|
// +build amd64 arm64
|
||||||
|
|
||||||
@ -19,7 +20,6 @@ func eventWriteTransfer(
|
|||||||
relatedActivityID *windows.GUID,
|
relatedActivityID *windows.GUID,
|
||||||
dataDescriptorCount uint32,
|
dataDescriptorCount uint32,
|
||||||
dataDescriptors *eventDataDescriptor) (win32err error) {
|
dataDescriptors *eventDataDescriptor) (win32err error) {
|
||||||
|
|
||||||
return eventWriteTransfer_64(
|
return eventWriteTransfer_64(
|
||||||
providerHandle,
|
providerHandle,
|
||||||
descriptor,
|
descriptor,
|
||||||
@ -34,7 +34,6 @@ func eventSetInformation(
|
|||||||
class eventInfoClass,
|
class eventInfoClass,
|
||||||
information uintptr,
|
information uintptr,
|
||||||
length uint32) (win32err error) {
|
length uint32) (win32err error) {
|
||||||
|
|
||||||
return eventSetInformation_64(
|
return eventSetInformation_64(
|
||||||
providerHandle,
|
providerHandle,
|
||||||
class,
|
class,
|
||||||
@ -46,7 +45,21 @@ func eventSetInformation(
|
|||||||
// for provider notifications. Because Go has trouble with callback arguments of
|
// for provider notifications. Because Go has trouble with callback arguments of
|
||||||
// different size, it has only pointer-sized arguments, which are then cast to
|
// different size, it has only pointer-sized arguments, which are then cast to
|
||||||
// the appropriate types when calling providerCallback.
|
// the appropriate types when calling providerCallback.
|
||||||
func providerCallbackAdapter(sourceID *guid.GUID, state uintptr, level uintptr, matchAnyKeyword uintptr, matchAllKeyword uintptr, filterData uintptr, i uintptr) uintptr {
|
func providerCallbackAdapter(
|
||||||
providerCallback(*sourceID, ProviderState(state), Level(level), uint64(matchAnyKeyword), uint64(matchAllKeyword), filterData, i)
|
sourceID *guid.GUID,
|
||||||
|
state uintptr,
|
||||||
|
level uintptr,
|
||||||
|
matchAnyKeyword uintptr,
|
||||||
|
matchAllKeyword uintptr,
|
||||||
|
filterData uintptr,
|
||||||
|
i uintptr,
|
||||||
|
) uintptr {
|
||||||
|
providerCallback(*sourceID,
|
||||||
|
ProviderState(state),
|
||||||
|
Level(level),
|
||||||
|
uint64(matchAnyKeyword),
|
||||||
|
uint64(matchAllKeyword),
|
||||||
|
filterData,
|
||||||
|
i)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
4
vendor/github.com/Microsoft/go-winio/pkg/etw/zsyscall_windows.go
generated
vendored
4
vendor/github.com/Microsoft/go-winio/pkg/etw/zsyscall_windows.go
generated
vendored
@ -1,4 +1,6 @@
|
|||||||
// Code generated by 'go generate'; DO NOT EDIT.
|
//go:build windows
|
||||||
|
|
||||||
|
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
|
||||||
|
|
||||||
package etw
|
package etw
|
||||||
|
|
||||||
|
87
vendor/github.com/Microsoft/go-winio/pkg/etwlogrus/hook.go
generated
vendored
87
vendor/github.com/Microsoft/go-winio/pkg/etwlogrus/hook.go
generated
vendored
@ -1,40 +1,79 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package etwlogrus
|
package etwlogrus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/Microsoft/go-winio/pkg/etw"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/pkg/etw"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defaultEventName = "LogrusEntry"
|
||||||
|
|
||||||
|
// ErrNoProvider is returned when a hook is created without a provider being configured.
|
||||||
|
var ErrNoProvider = errors.New("no ETW registered provider")
|
||||||
|
|
||||||
|
// HookOpt is an option to change the behavior of the Logrus ETW hook.
|
||||||
|
type HookOpt func(*Hook) error
|
||||||
|
|
||||||
// Hook is a Logrus hook which logs received events to ETW.
|
// Hook is a Logrus hook which logs received events to ETW.
|
||||||
type Hook struct {
|
type Hook struct {
|
||||||
provider *etw.Provider
|
provider *etw.Provider
|
||||||
closeProvider bool
|
closeProvider bool
|
||||||
|
// allows setting the entry name
|
||||||
|
getName func(*logrus.Entry) string
|
||||||
|
// returns additional options to add to the event
|
||||||
|
getEventsOpts func(*logrus.Entry) []etw.EventOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHook registers a new ETW provider and returns a hook to log from it. The
|
// NewHook registers a new ETW provider and returns a hook to log from it.
|
||||||
// provider will be closed when the hook is closed.
|
// The provider will be closed when the hook is closed.
|
||||||
func NewHook(providerName string) (*Hook, error) {
|
func NewHook(providerName string, opts ...HookOpt) (*Hook, error) {
|
||||||
provider, err := etw.NewProvider(providerName, nil)
|
opts = append(opts, WithNewETWProvider(providerName))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return NewHookFromOpts(opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHookFromProvider creates a new hook based on an existing ETW provider.
|
||||||
|
// The provider will not be closed when the hook is closed.
|
||||||
|
func NewHookFromProvider(provider *etw.Provider, opts ...HookOpt) (*Hook, error) {
|
||||||
|
opts = append(opts, WithExistingETWProvider(provider))
|
||||||
|
|
||||||
|
return NewHookFromOpts(opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHookFromOpts creates a new hook with the provided options.
|
||||||
|
// An error is returned if the hook does not have a valid provider.
|
||||||
|
func NewHookFromOpts(opts ...HookOpt) (*Hook, error) {
|
||||||
|
h := defaultHook()
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
if err := o(h); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return h, h.validate()
|
||||||
return &Hook{provider, true}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHookFromProvider creates a new hook based on an existing ETW provider. The
|
func defaultHook() *Hook {
|
||||||
// provider will not be closed when the hook is closed.
|
h := &Hook{}
|
||||||
func NewHookFromProvider(provider *etw.Provider) (*Hook, error) {
|
return h
|
||||||
return &Hook{provider, false}, nil
|
}
|
||||||
|
|
||||||
|
func (h *Hook) validate() error {
|
||||||
|
if h.provider == nil {
|
||||||
|
return ErrNoProvider
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Levels returns the set of levels that this hook wants to receive log entries
|
// Levels returns the set of levels that this hook wants to receive log entries
|
||||||
// for.
|
// for.
|
||||||
func (h *Hook) Levels() []logrus.Level {
|
func (*Hook) Levels() []logrus.Level {
|
||||||
return logrus.AllLevels
|
return logrus.AllLevels
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +97,21 @@ func (h *Hook) Fire(e *logrus.Entry) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := defaultEventName
|
||||||
|
if h.getName != nil {
|
||||||
|
if n := h.getName(e); n != "" {
|
||||||
|
name = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// extra room for two more options in addition to log level to avoid repeated reallocations
|
||||||
|
// if the user also provides options
|
||||||
|
opts := make([]etw.EventOpt, 0, 3)
|
||||||
|
opts = append(opts, etw.WithLevel(level))
|
||||||
|
if h.getEventsOpts != nil {
|
||||||
|
opts = append(opts, h.getEventsOpts(e)...)
|
||||||
|
}
|
||||||
|
|
||||||
// Sort the fields by name so they are consistent in each instance
|
// Sort the fields by name so they are consistent in each instance
|
||||||
// of an event. Otherwise, the fields don't line up in WPA.
|
// of an event. Otherwise, the fields don't line up in WPA.
|
||||||
names := make([]string, 0, len(e.Data))
|
names := make([]string, 0, len(e.Data))
|
||||||
@ -88,10 +142,7 @@ func (h *Hook) Fire(e *logrus.Entry) error {
|
|||||||
// as a session listening for the event having no available space in its
|
// as a session listening for the event having no available space in its
|
||||||
// buffers). Therefore, we don't return the error from WriteEvent, as it is
|
// buffers). Therefore, we don't return the error from WriteEvent, as it is
|
||||||
// just noise in many cases.
|
// just noise in many cases.
|
||||||
h.provider.WriteEvent(
|
_ = h.provider.WriteEvent(name, opts, fields)
|
||||||
"LogrusEntry",
|
|
||||||
etw.WithEventOpts(etw.WithLevel(level)),
|
|
||||||
fields)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
53
vendor/github.com/Microsoft/go-winio/pkg/etwlogrus/opts.go
generated
vendored
Normal file
53
vendor/github.com/Microsoft/go-winio/pkg/etwlogrus/opts.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package etwlogrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/pkg/etw"
|
||||||
|
)
|
||||||
|
|
||||||
|
// etw provider
|
||||||
|
|
||||||
|
// WithNewETWProvider registers a new ETW provider and sets the hook to log using it.
|
||||||
|
// The provider will be closed when the hook is closed.
|
||||||
|
func WithNewETWProvider(n string) HookOpt {
|
||||||
|
return func(h *Hook) error {
|
||||||
|
provider, err := etw.NewProvider(n, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
h.provider = provider
|
||||||
|
h.closeProvider = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithExistingETWProvider configures the hook to use an existing ETW provider.
|
||||||
|
// The provider will not be closed when the hook is closed.
|
||||||
|
func WithExistingETWProvider(p *etw.Provider) HookOpt {
|
||||||
|
return func(h *Hook) error {
|
||||||
|
h.provider = p
|
||||||
|
h.closeProvider = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithGetName sets the ETW EventName of an event to the value returned by f
|
||||||
|
// If the name is empty, the default event name will be used.
|
||||||
|
func WithGetName(f func(*logrus.Entry) string) HookOpt {
|
||||||
|
return func(h *Hook) error {
|
||||||
|
h.getName = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithEventOpts allows additional ETW event properties (keywords, tags, etc.) to be specified.
|
||||||
|
func WithEventOpts(f func(*logrus.Entry) []etw.EventOpt) HookOpt {
|
||||||
|
return func(h *Hook) error {
|
||||||
|
h.getEventsOpts = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
2
vendor/github.com/Microsoft/go-winio/pkg/fs/fs_windows.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/pkg/fs/fs_windows.go
generated
vendored
@ -27,5 +27,5 @@ func GetFileSystemType(path string) (fsType string, err error) {
|
|||||||
drive += `\`
|
drive += `\`
|
||||||
err = windows.GetVolumeInformation(windows.StringToUTF16Ptr(drive), nil, 0, nil, nil, nil, &buf[0], size)
|
err = windows.GetVolumeInformation(windows.StringToUTF16Ptr(drive), nil, 0, nil, nil, nil, &buf[0], size)
|
||||||
fsType = windows.UTF16ToString(buf)
|
fsType = windows.UTF16ToString(buf)
|
||||||
return
|
return fsType, err
|
||||||
}
|
}
|
||||||
|
16
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
16
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
@ -1,5 +1,3 @@
|
|||||||
// +build windows
|
|
||||||
|
|
||||||
// Package guid provides a GUID type. The backing structure for a GUID is
|
// 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.
|
// 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,
|
// There are two main binary encodings used for a GUID, the big-endian encoding,
|
||||||
@ -9,24 +7,26 @@ package guid
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha1"
|
"crypto/sha1" //nolint:gosec // not used for secure application
|
||||||
"encoding"
|
"encoding"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:generate go run golang.org/x/tools/cmd/stringer -type=Variant -trimprefix=Variant -linecomment
|
||||||
|
|
||||||
// Variant specifies which GUID variant (or "type") of the GUID. It determines
|
// Variant specifies which GUID variant (or "type") of the GUID. It determines
|
||||||
// how the entirety of the rest of the GUID is interpreted.
|
// how the entirety of the rest of the GUID is interpreted.
|
||||||
type Variant uint8
|
type Variant uint8
|
||||||
|
|
||||||
// The variants specified by RFC 4122.
|
// The variants specified by RFC 4122 section 4.1.1.
|
||||||
const (
|
const (
|
||||||
// VariantUnknown specifies a GUID variant which does not conform to one of
|
// VariantUnknown specifies a GUID variant which does not conform to one of
|
||||||
// the variant encodings specified in RFC 4122.
|
// the variant encodings specified in RFC 4122.
|
||||||
VariantUnknown Variant = iota
|
VariantUnknown Variant = iota
|
||||||
VariantNCS
|
VariantNCS
|
||||||
VariantRFC4122
|
VariantRFC4122 // RFC 4122
|
||||||
VariantMicrosoft
|
VariantMicrosoft
|
||||||
VariantFuture
|
VariantFuture
|
||||||
)
|
)
|
||||||
@ -36,6 +36,10 @@ const (
|
|||||||
// hash of an input string.
|
// hash of an input string.
|
||||||
type Version uint8
|
type Version uint8
|
||||||
|
|
||||||
|
func (v Version) String() string {
|
||||||
|
return strconv.FormatUint(uint64(v), 10)
|
||||||
|
}
|
||||||
|
|
||||||
var _ = (encoding.TextMarshaler)(GUID{})
|
var _ = (encoding.TextMarshaler)(GUID{})
|
||||||
var _ = (encoding.TextUnmarshaler)(&GUID{})
|
var _ = (encoding.TextUnmarshaler)(&GUID{})
|
||||||
|
|
||||||
@ -61,7 +65,7 @@ func NewV4() (GUID, error) {
|
|||||||
// big-endian UTF16 stream of bytes. If that is desired, the string can be
|
// big-endian UTF16 stream of bytes. If that is desired, the string can be
|
||||||
// encoded as such before being passed to this function.
|
// encoded as such before being passed to this function.
|
||||||
func NewV5(namespace GUID, name []byte) (GUID, error) {
|
func NewV5(namespace GUID, name []byte) (GUID, error) {
|
||||||
b := sha1.New()
|
b := sha1.New() //nolint:gosec // not used for secure application
|
||||||
namespaceBytes := namespace.ToArray()
|
namespaceBytes := namespace.ToArray()
|
||||||
b.Write(namespaceBytes[:])
|
b.Write(namespaceBytes[:])
|
||||||
b.Write(name)
|
b.Write(name)
|
||||||
|
1
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
generated
vendored
1
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package guid
|
package guid
|
||||||
|
3
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
generated
vendored
3
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package guid
|
package guid
|
||||||
|
|
||||||
import "golang.org/x/sys/windows"
|
import "golang.org/x/sys/windows"
|
||||||
|
27
vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go
generated
vendored
Normal file
27
vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Code generated by "stringer -type=Variant -trimprefix=Variant -linecomment"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package guid
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[VariantUnknown-0]
|
||||||
|
_ = x[VariantNCS-1]
|
||||||
|
_ = x[VariantRFC4122-2]
|
||||||
|
_ = x[VariantMicrosoft-3]
|
||||||
|
_ = x[VariantFuture-4]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _Variant_name = "UnknownNCSRFC 4122MicrosoftFuture"
|
||||||
|
|
||||||
|
var _Variant_index = [...]uint8{0, 7, 10, 18, 27, 33}
|
||||||
|
|
||||||
|
func (i Variant) String() string {
|
||||||
|
if i >= Variant(len(_Variant_index)-1) {
|
||||||
|
return "Variant(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _Variant_name[_Variant_index[i]:_Variant_index[i+1]]
|
||||||
|
}
|
33
vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go
generated
vendored
33
vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package security
|
package security
|
||||||
@ -20,6 +21,7 @@ type (
|
|||||||
trusteeForm uint32
|
trusteeForm uint32
|
||||||
trusteeType uint32
|
trusteeType uint32
|
||||||
|
|
||||||
|
//nolint:structcheck // structcheck thinks fields are unused, but the are used to pass data to OS
|
||||||
explicitAccess struct {
|
explicitAccess struct {
|
||||||
accessPermissions accessMask
|
accessPermissions accessMask
|
||||||
accessMode accessMode
|
accessMode accessMode
|
||||||
@ -27,6 +29,7 @@ type (
|
|||||||
trustee trustee
|
trustee trustee
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:structcheck,unused // structcheck thinks fields are unused, but the are used to pass data to OS
|
||||||
trustee struct {
|
trustee struct {
|
||||||
multipleTrustee *trustee
|
multipleTrustee *trustee
|
||||||
multipleTrusteeOperation int32
|
multipleTrusteeOperation int32
|
||||||
@ -44,6 +47,7 @@ const (
|
|||||||
desiredAccessReadControl desiredAccess = 0x20000
|
desiredAccessReadControl desiredAccess = 0x20000
|
||||||
desiredAccessWriteDac desiredAccess = 0x40000
|
desiredAccessWriteDac desiredAccess = 0x40000
|
||||||
|
|
||||||
|
//cspell:disable-next-line
|
||||||
gvmga = "GrantVmGroupAccess:"
|
gvmga = "GrantVmGroupAccess:"
|
||||||
|
|
||||||
inheritModeNoInheritance inheritMode = 0x0
|
inheritModeNoInheritance inheritMode = 0x0
|
||||||
@ -56,9 +60,9 @@ const (
|
|||||||
shareModeRead shareMode = 0x1
|
shareModeRead shareMode = 0x1
|
||||||
shareModeWrite shareMode = 0x2
|
shareModeWrite shareMode = 0x2
|
||||||
|
|
||||||
sidVmGroup = "S-1-5-83-0"
|
sidVMGroup = "S-1-5-83-0"
|
||||||
|
|
||||||
trusteeFormIsSid trusteeForm = 0
|
trusteeFormIsSID trusteeForm = 0
|
||||||
|
|
||||||
trusteeTypeWellKnownGroup trusteeType = 5
|
trusteeTypeWellKnownGroup trusteeType = 5
|
||||||
)
|
)
|
||||||
@ -67,6 +71,8 @@ const (
|
|||||||
// include Grant ACE entries for the VM Group SID. This is a golang re-
|
// include Grant ACE entries for the VM Group SID. This is a golang re-
|
||||||
// implementation of the same function in vmcompute, just not exported in
|
// implementation of the same function in vmcompute, just not exported in
|
||||||
// RS5. Which kind of sucks. Sucks a lot :/
|
// RS5. Which kind of sucks. Sucks a lot :/
|
||||||
|
//
|
||||||
|
//revive:disable-next-line:var-naming VM, not Vm
|
||||||
func GrantVmGroupAccess(name string) error {
|
func GrantVmGroupAccess(name string) error {
|
||||||
// Stat (to determine if `name` is a directory).
|
// Stat (to determine if `name` is a directory).
|
||||||
s, err := os.Stat(name)
|
s, err := os.Stat(name)
|
||||||
@ -79,7 +85,7 @@ func GrantVmGroupAccess(name string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err // Already wrapped
|
return err // Already wrapped
|
||||||
}
|
}
|
||||||
defer syscall.CloseHandle(fd)
|
defer syscall.CloseHandle(fd) //nolint:errcheck
|
||||||
|
|
||||||
// Get the current DACL and Security Descriptor. Must defer LocalFree on success.
|
// Get the current DACL and Security Descriptor. Must defer LocalFree on success.
|
||||||
ot := objectTypeFileObject
|
ot := objectTypeFileObject
|
||||||
@ -89,7 +95,7 @@ func GrantVmGroupAccess(name string) error {
|
|||||||
if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil {
|
if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil {
|
||||||
return fmt.Errorf("%s GetSecurityInfo %s: %w", gvmga, name, err)
|
return fmt.Errorf("%s GetSecurityInfo %s: %w", gvmga, name, err)
|
||||||
}
|
}
|
||||||
defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd)))
|
defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd))) //nolint:errcheck
|
||||||
|
|
||||||
// Generate a new DACL which is the current DACL with the required ACEs added.
|
// Generate a new DACL which is the current DACL with the required ACEs added.
|
||||||
// Must defer LocalFree on success.
|
// Must defer LocalFree on success.
|
||||||
@ -97,7 +103,7 @@ func GrantVmGroupAccess(name string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err // Already wrapped
|
return err // Already wrapped
|
||||||
}
|
}
|
||||||
defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL)))
|
defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL))) //nolint:errcheck
|
||||||
|
|
||||||
// And finally use SetSecurityInfo to apply the updated DACL.
|
// And finally use SetSecurityInfo to apply the updated DACL.
|
||||||
if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil {
|
if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil {
|
||||||
@ -110,16 +116,19 @@ func GrantVmGroupAccess(name string) error {
|
|||||||
// createFile is a helper function to call [Nt]CreateFile to get a handle to
|
// createFile is a helper function to call [Nt]CreateFile to get a handle to
|
||||||
// the file or directory.
|
// the file or directory.
|
||||||
func createFile(name string, isDir bool) (syscall.Handle, error) {
|
func createFile(name string, isDir bool) (syscall.Handle, error) {
|
||||||
namep := syscall.StringToUTF16(name)
|
namep, err := syscall.UTF16FromString(name)
|
||||||
|
if err != nil {
|
||||||
|
return syscall.InvalidHandle, fmt.Errorf("could not convernt name to UTF-16: %w", err)
|
||||||
|
}
|
||||||
da := uint32(desiredAccessReadControl | desiredAccessWriteDac)
|
da := uint32(desiredAccessReadControl | desiredAccessWriteDac)
|
||||||
sm := uint32(shareModeRead | shareModeWrite)
|
sm := uint32(shareModeRead | shareModeWrite)
|
||||||
fa := uint32(syscall.FILE_ATTRIBUTE_NORMAL)
|
fa := uint32(syscall.FILE_ATTRIBUTE_NORMAL)
|
||||||
if isDir {
|
if isDir {
|
||||||
fa = uint32(fa | syscall.FILE_FLAG_BACKUP_SEMANTICS)
|
fa |= syscall.FILE_FLAG_BACKUP_SEMANTICS
|
||||||
}
|
}
|
||||||
fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0)
|
fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("%s syscall.CreateFile %s: %w", gvmga, name, err)
|
return syscall.InvalidHandle, fmt.Errorf("%s syscall.CreateFile %s: %w", gvmga, name, err)
|
||||||
}
|
}
|
||||||
return fd, nil
|
return fd, nil
|
||||||
}
|
}
|
||||||
@ -128,9 +137,9 @@ func createFile(name string, isDir bool) (syscall.Handle, error) {
|
|||||||
// The caller is responsible for LocalFree of the returned DACL on success.
|
// The caller is responsible for LocalFree of the returned DACL on success.
|
||||||
func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintptr, error) {
|
func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintptr, error) {
|
||||||
// Generate pointers to the SIDs based on the string SIDs
|
// Generate pointers to the SIDs based on the string SIDs
|
||||||
sid, err := syscall.StringToSid(sidVmGroup)
|
sid, err := syscall.StringToSid(sidVMGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("%s syscall.StringToSid %s %s: %w", gvmga, name, sidVmGroup, err)
|
return 0, fmt.Errorf("%s syscall.StringToSid %s %s: %w", gvmga, name, sidVMGroup, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
inheritance := inheritModeNoInheritance
|
inheritance := inheritModeNoInheritance
|
||||||
@ -139,12 +148,12 @@ func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintp
|
|||||||
}
|
}
|
||||||
|
|
||||||
eaArray := []explicitAccess{
|
eaArray := []explicitAccess{
|
||||||
explicitAccess{
|
{
|
||||||
accessPermissions: accessMaskDesiredPermission,
|
accessPermissions: accessMaskDesiredPermission,
|
||||||
accessMode: accessModeGrant,
|
accessMode: accessModeGrant,
|
||||||
inheritance: inheritance,
|
inheritance: inheritance,
|
||||||
trustee: trustee{
|
trustee: trustee{
|
||||||
trusteeForm: trusteeFormIsSid,
|
trusteeForm: trusteeFormIsSID,
|
||||||
trusteeType: trusteeTypeWellKnownGroup,
|
trusteeType: trusteeTypeWellKnownGroup,
|
||||||
name: uintptr(unsafe.Pointer(sid)),
|
name: uintptr(unsafe.Pointer(sid)),
|
||||||
},
|
},
|
||||||
|
2
vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
package security
|
package security
|
||||||
|
|
||||||
//go:generate go run mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
|
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go syscall_windows.go
|
||||||
|
|
||||||
//sys getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (win32err error) = advapi32.GetSecurityInfo
|
//sys getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (win32err error) = advapi32.GetSecurityInfo
|
||||||
//sys setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (win32err error) = advapi32.SetSecurityInfo
|
//sys setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (win32err error) = advapi32.SetSecurityInfo
|
||||||
|
4
vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go
generated
vendored
4
vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go
generated
vendored
@ -1,4 +1,6 @@
|
|||||||
// Code generated by 'go generate'; DO NOT EDIT.
|
//go:build windows
|
||||||
|
|
||||||
|
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
|
||||||
|
|
||||||
package security
|
package security
|
||||||
|
|
||||||
|
32
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
32
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package winio
|
package winio
|
||||||
@ -24,22 +25,17 @@ import (
|
|||||||
//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
|
//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SE_PRIVILEGE_ENABLED = 2
|
//revive:disable-next-line:var-naming ALL_CAPS
|
||||||
|
SE_PRIVILEGE_ENABLED = windows.SE_PRIVILEGE_ENABLED
|
||||||
|
|
||||||
ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
|
//revive:disable-next-line:var-naming ALL_CAPS
|
||||||
|
ERROR_NOT_ALL_ASSIGNED syscall.Errno = windows.ERROR_NOT_ALL_ASSIGNED
|
||||||
|
|
||||||
SeBackupPrivilege = "SeBackupPrivilege"
|
SeBackupPrivilege = "SeBackupPrivilege"
|
||||||
SeRestorePrivilege = "SeRestorePrivilege"
|
SeRestorePrivilege = "SeRestorePrivilege"
|
||||||
SeSecurityPrivilege = "SeSecurityPrivilege"
|
SeSecurityPrivilege = "SeSecurityPrivilege"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
securityAnonymous = iota
|
|
||||||
securityIdentification
|
|
||||||
securityImpersonation
|
|
||||||
securityDelegation
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
privNames = make(map[string]uint64)
|
privNames = make(map[string]uint64)
|
||||||
privNameMutex sync.Mutex
|
privNameMutex sync.Mutex
|
||||||
@ -51,11 +47,9 @@ type PrivilegeError struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *PrivilegeError) Error() string {
|
func (e *PrivilegeError) Error() string {
|
||||||
s := ""
|
s := "Could not enable privilege "
|
||||||
if len(e.privileges) > 1 {
|
if len(e.privileges) > 1 {
|
||||||
s = "Could not enable privileges "
|
s = "Could not enable privileges "
|
||||||
} else {
|
|
||||||
s = "Could not enable privilege "
|
|
||||||
}
|
}
|
||||||
for i, p := range e.privileges {
|
for i, p := range e.privileges {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
@ -94,7 +88,7 @@ func RunWithPrivileges(names []string, fn func() error) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func mapPrivileges(names []string) ([]uint64, error) {
|
func mapPrivileges(names []string) ([]uint64, error) {
|
||||||
var privileges []uint64
|
privileges := make([]uint64, 0, len(names))
|
||||||
privNameMutex.Lock()
|
privNameMutex.Lock()
|
||||||
defer privNameMutex.Unlock()
|
defer privNameMutex.Unlock()
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
@ -127,7 +121,7 @@ func enableDisableProcessPrivilege(names []string, action uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
p, _ := windows.GetCurrentProcess()
|
p := windows.CurrentProcess()
|
||||||
var token windows.Token
|
var token windows.Token
|
||||||
err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token)
|
err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -140,10 +134,10 @@ func enableDisableProcessPrivilege(names []string, action uint32) error {
|
|||||||
|
|
||||||
func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error {
|
func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
|
_ = binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
|
||||||
for _, p := range privileges {
|
for _, p := range privileges {
|
||||||
binary.Write(&b, binary.LittleEndian, p)
|
_ = binary.Write(&b, binary.LittleEndian, p)
|
||||||
binary.Write(&b, binary.LittleEndian, action)
|
_ = binary.Write(&b, binary.LittleEndian, action)
|
||||||
}
|
}
|
||||||
prevState := make([]byte, b.Len())
|
prevState := make([]byte, b.Len())
|
||||||
reqSize := uint32(0)
|
reqSize := uint32(0)
|
||||||
@ -151,7 +145,7 @@ func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) e
|
|||||||
if !success {
|
if !success {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err == ERROR_NOT_ALL_ASSIGNED {
|
if err == ERROR_NOT_ALL_ASSIGNED { //nolint:errorlint // err is Errno
|
||||||
return &PrivilegeError{privileges}
|
return &PrivilegeError{privileges}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -177,7 +171,7 @@ func getPrivilegeName(luid uint64) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newThreadToken() (windows.Token, error) {
|
func newThreadToken() (windows.Token, error) {
|
||||||
err := impersonateSelf(securityImpersonation)
|
err := impersonateSelf(windows.SecurityImpersonation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
11
vendor/github.com/Microsoft/go-winio/reparse.go
generated
vendored
11
vendor/github.com/Microsoft/go-winio/reparse.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package winio
|
package winio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -113,16 +116,16 @@ func EncodeReparsePoint(rp *ReparsePoint) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
binary.Write(&b, binary.LittleEndian, &data)
|
_ = binary.Write(&b, binary.LittleEndian, &data)
|
||||||
if !rp.IsMountPoint {
|
if !rp.IsMountPoint {
|
||||||
flags := uint32(0)
|
flags := uint32(0)
|
||||||
if relative {
|
if relative {
|
||||||
flags |= 1
|
flags |= 1
|
||||||
}
|
}
|
||||||
binary.Write(&b, binary.LittleEndian, flags)
|
_ = binary.Write(&b, binary.LittleEndian, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
binary.Write(&b, binary.LittleEndian, ntTarget16)
|
_ = binary.Write(&b, binary.LittleEndian, ntTarget16)
|
||||||
binary.Write(&b, binary.LittleEndian, target16)
|
_ = binary.Write(&b, binary.LittleEndian, target16)
|
||||||
return b.Bytes()
|
return b.Bytes()
|
||||||
}
|
}
|
||||||
|
64
vendor/github.com/Microsoft/go-winio/sd.go
generated
vendored
64
vendor/github.com/Microsoft/go-winio/sd.go
generated
vendored
@ -1,23 +1,25 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package winio
|
package winio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
|
//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
|
||||||
|
//sys lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountSidW
|
||||||
//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
|
//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
|
||||||
|
//sys convertStringSidToSid(str *uint16, sid **byte) (err error) = advapi32.ConvertStringSidToSidW
|
||||||
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
|
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
|
||||||
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
|
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
|
||||||
//sys localFree(mem uintptr) = LocalFree
|
//sys localFree(mem uintptr) = LocalFree
|
||||||
//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
|
//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
|
||||||
|
|
||||||
const (
|
|
||||||
cERROR_NONE_MAPPED = syscall.Errno(1332)
|
|
||||||
)
|
|
||||||
|
|
||||||
type AccountLookupError struct {
|
type AccountLookupError struct {
|
||||||
Name string
|
Name string
|
||||||
Err error
|
Err error
|
||||||
@ -28,8 +30,10 @@ func (e *AccountLookupError) Error() string {
|
|||||||
return "lookup account: empty account name specified"
|
return "lookup account: empty account name specified"
|
||||||
}
|
}
|
||||||
var s string
|
var s string
|
||||||
switch e.Err {
|
switch {
|
||||||
case cERROR_NONE_MAPPED:
|
case errors.Is(e.Err, windows.ERROR_INVALID_SID):
|
||||||
|
s = "the security ID structure is invalid"
|
||||||
|
case errors.Is(e.Err, windows.ERROR_NONE_MAPPED):
|
||||||
s = "not found"
|
s = "not found"
|
||||||
default:
|
default:
|
||||||
s = e.Err.Error()
|
s = e.Err.Error()
|
||||||
@ -37,6 +41,8 @@ func (e *AccountLookupError) Error() string {
|
|||||||
return "lookup account " + e.Name + ": " + s
|
return "lookup account " + e.Name + ": " + s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *AccountLookupError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
type SddlConversionError struct {
|
type SddlConversionError struct {
|
||||||
Sddl string
|
Sddl string
|
||||||
Err error
|
Err error
|
||||||
@ -46,15 +52,19 @@ func (e *SddlConversionError) Error() string {
|
|||||||
return "convert " + e.Sddl + ": " + e.Err.Error()
|
return "convert " + e.Sddl + ": " + e.Err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *SddlConversionError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
// LookupSidByName looks up the SID of an account by name
|
// LookupSidByName looks up the SID of an account by name
|
||||||
|
//
|
||||||
|
//revive:disable-next-line:var-naming SID, not Sid
|
||||||
func LookupSidByName(name string) (sid string, err error) {
|
func LookupSidByName(name string) (sid string, err error) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return "", &AccountLookupError{name, cERROR_NONE_MAPPED}
|
return "", &AccountLookupError{name, windows.ERROR_NONE_MAPPED}
|
||||||
}
|
}
|
||||||
|
|
||||||
var sidSize, sidNameUse, refDomainSize uint32
|
var sidSize, sidNameUse, refDomainSize uint32
|
||||||
err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
|
err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
|
||||||
if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER {
|
if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno
|
||||||
return "", &AccountLookupError{name, err}
|
return "", &AccountLookupError{name, err}
|
||||||
}
|
}
|
||||||
sidBuffer := make([]byte, sidSize)
|
sidBuffer := make([]byte, sidSize)
|
||||||
@ -73,6 +83,42 @@ func LookupSidByName(name string) (sid string, err error) {
|
|||||||
return sid, nil
|
return sid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LookupNameBySid looks up the name of an account by SID
|
||||||
|
//
|
||||||
|
//revive:disable-next-line:var-naming SID, not Sid
|
||||||
|
func LookupNameBySid(sid string) (name string, err error) {
|
||||||
|
if sid == "" {
|
||||||
|
return "", &AccountLookupError{sid, windows.ERROR_NONE_MAPPED}
|
||||||
|
}
|
||||||
|
|
||||||
|
sidBuffer, err := windows.UTF16PtrFromString(sid)
|
||||||
|
if err != nil {
|
||||||
|
return "", &AccountLookupError{sid, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sidPtr *byte
|
||||||
|
if err = convertStringSidToSid(sidBuffer, &sidPtr); err != nil {
|
||||||
|
return "", &AccountLookupError{sid, err}
|
||||||
|
}
|
||||||
|
defer localFree(uintptr(unsafe.Pointer(sidPtr)))
|
||||||
|
|
||||||
|
var nameSize, refDomainSize, sidNameUse uint32
|
||||||
|
err = lookupAccountSid(nil, sidPtr, nil, &nameSize, nil, &refDomainSize, &sidNameUse)
|
||||||
|
if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno
|
||||||
|
return "", &AccountLookupError{sid, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
nameBuffer := make([]uint16, nameSize)
|
||||||
|
refDomainBuffer := make([]uint16, refDomainSize)
|
||||||
|
err = lookupAccountSid(nil, sidPtr, &nameBuffer[0], &nameSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse)
|
||||||
|
if err != nil {
|
||||||
|
return "", &AccountLookupError{sid, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
name = windows.UTF16ToString(nameBuffer)
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
|
func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
|
||||||
var sdBuffer uintptr
|
var sdBuffer uintptr
|
||||||
err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
|
err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
|
||||||
@ -87,7 +133,7 @@ func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
|
|||||||
|
|
||||||
func SecurityDescriptorToSddl(sd []byte) (string, error) {
|
func SecurityDescriptorToSddl(sd []byte) (string, error) {
|
||||||
var sddl *uint16
|
var sddl *uint16
|
||||||
// The returned string length seems to including an aribtrary number of terminating NULs.
|
// The returned string length seems to include an arbitrary number of terminating NULs.
|
||||||
// Don't use it.
|
// Don't use it.
|
||||||
err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
|
err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
4
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
4
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
package winio
|
package winio
|
||||||
|
|
||||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
|
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go ./*.go
|
||||||
|
5
vendor/github.com/Microsoft/go-winio/tools.go
generated
vendored
Normal file
5
vendor/github.com/Microsoft/go-winio/tools.go
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//go:build tools
|
||||||
|
|
||||||
|
package winio
|
||||||
|
|
||||||
|
import _ "golang.org/x/tools/cmd/stringer"
|
59
vendor/github.com/Microsoft/go-winio/vhd/vhd.go
generated
vendored
59
vendor/github.com/Microsoft/go-winio/vhd/vhd.go
generated
vendored
@ -11,7 +11,7 @@ import (
|
|||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run mksyscall_windows.go -output zvhd_windows.go vhd.go
|
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zvhd_windows.go vhd.go
|
||||||
|
|
||||||
//sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) = virtdisk.CreateVirtualDisk
|
//sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) = virtdisk.CreateVirtualDisk
|
||||||
//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) = virtdisk.OpenVirtualDisk
|
//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) = virtdisk.OpenVirtualDisk
|
||||||
@ -62,8 +62,8 @@ type OpenVirtualDiskParameters struct {
|
|||||||
Version2 OpenVersion2
|
Version2 OpenVersion2
|
||||||
}
|
}
|
||||||
|
|
||||||
// The higher level `OpenVersion2` struct uses bools to refer to `GetInfoOnly` and `ReadOnly` for ease of use. However,
|
// The higher level `OpenVersion2` struct uses `bool`s to refer to `GetInfoOnly` and `ReadOnly` for ease of use. However,
|
||||||
// the internal windows structure uses `BOOLS` aka int32s for these types. `openVersion2` is used for translating
|
// the internal windows structure uses `BOOL`s aka int32s for these types. `openVersion2` is used for translating
|
||||||
// `OpenVersion2` fields to the correct windows internal field types on the `Open____` methods.
|
// `OpenVersion2` fields to the correct windows internal field types on the `Open____` methods.
|
||||||
type openVersion2 struct {
|
type openVersion2 struct {
|
||||||
getInfoOnly int32
|
getInfoOnly int32
|
||||||
@ -87,9 +87,10 @@ type AttachVirtualDiskParameters struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
//revive:disable-next-line:var-naming ALL_CAPS
|
||||||
VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 0x3
|
VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 0x3
|
||||||
|
|
||||||
// Access Mask for opening a VHD
|
// Access Mask for opening a VHD.
|
||||||
VirtualDiskAccessNone VirtualDiskAccessMask = 0x00000000
|
VirtualDiskAccessNone VirtualDiskAccessMask = 0x00000000
|
||||||
VirtualDiskAccessAttachRO VirtualDiskAccessMask = 0x00010000
|
VirtualDiskAccessAttachRO VirtualDiskAccessMask = 0x00010000
|
||||||
VirtualDiskAccessAttachRW VirtualDiskAccessMask = 0x00020000
|
VirtualDiskAccessAttachRW VirtualDiskAccessMask = 0x00020000
|
||||||
@ -101,7 +102,7 @@ const (
|
|||||||
VirtualDiskAccessAll VirtualDiskAccessMask = 0x003f0000
|
VirtualDiskAccessAll VirtualDiskAccessMask = 0x003f0000
|
||||||
VirtualDiskAccessWritable VirtualDiskAccessMask = 0x00320000
|
VirtualDiskAccessWritable VirtualDiskAccessMask = 0x00320000
|
||||||
|
|
||||||
// Flags for creating a VHD
|
// Flags for creating a VHD.
|
||||||
CreateVirtualDiskFlagNone CreateVirtualDiskFlag = 0x0
|
CreateVirtualDiskFlagNone CreateVirtualDiskFlag = 0x0
|
||||||
CreateVirtualDiskFlagFullPhysicalAllocation CreateVirtualDiskFlag = 0x1
|
CreateVirtualDiskFlagFullPhysicalAllocation CreateVirtualDiskFlag = 0x1
|
||||||
CreateVirtualDiskFlagPreventWritesToSourceDisk CreateVirtualDiskFlag = 0x2
|
CreateVirtualDiskFlagPreventWritesToSourceDisk CreateVirtualDiskFlag = 0x2
|
||||||
@ -109,12 +110,12 @@ const (
|
|||||||
CreateVirtualDiskFlagCreateBackingStorage CreateVirtualDiskFlag = 0x8
|
CreateVirtualDiskFlagCreateBackingStorage CreateVirtualDiskFlag = 0x8
|
||||||
CreateVirtualDiskFlagUseChangeTrackingSourceLimit CreateVirtualDiskFlag = 0x10
|
CreateVirtualDiskFlagUseChangeTrackingSourceLimit CreateVirtualDiskFlag = 0x10
|
||||||
CreateVirtualDiskFlagPreserveParentChangeTrackingState CreateVirtualDiskFlag = 0x20
|
CreateVirtualDiskFlagPreserveParentChangeTrackingState CreateVirtualDiskFlag = 0x20
|
||||||
CreateVirtualDiskFlagVhdSetUseOriginalBackingStorage CreateVirtualDiskFlag = 0x40
|
CreateVirtualDiskFlagVhdSetUseOriginalBackingStorage CreateVirtualDiskFlag = 0x40 //revive:disable-line:var-naming VHD, not Vhd
|
||||||
CreateVirtualDiskFlagSparseFile CreateVirtualDiskFlag = 0x80
|
CreateVirtualDiskFlagSparseFile CreateVirtualDiskFlag = 0x80
|
||||||
CreateVirtualDiskFlagPmemCompatible CreateVirtualDiskFlag = 0x100
|
CreateVirtualDiskFlagPmemCompatible CreateVirtualDiskFlag = 0x100 //revive:disable-line:var-naming PMEM, not Pmem
|
||||||
CreateVirtualDiskFlagSupportCompressedVolumes CreateVirtualDiskFlag = 0x200
|
CreateVirtualDiskFlagSupportCompressedVolumes CreateVirtualDiskFlag = 0x200
|
||||||
|
|
||||||
// Flags for opening a VHD
|
// Flags for opening a VHD.
|
||||||
OpenVirtualDiskFlagNone VirtualDiskFlag = 0x00000000
|
OpenVirtualDiskFlagNone VirtualDiskFlag = 0x00000000
|
||||||
OpenVirtualDiskFlagNoParents VirtualDiskFlag = 0x00000001
|
OpenVirtualDiskFlagNoParents VirtualDiskFlag = 0x00000001
|
||||||
OpenVirtualDiskFlagBlankFile VirtualDiskFlag = 0x00000002
|
OpenVirtualDiskFlagBlankFile VirtualDiskFlag = 0x00000002
|
||||||
@ -127,7 +128,7 @@ const (
|
|||||||
OpenVirtualDiskFlagNoWriteHardening VirtualDiskFlag = 0x00000100
|
OpenVirtualDiskFlagNoWriteHardening VirtualDiskFlag = 0x00000100
|
||||||
OpenVirtualDiskFlagSupportCompressedVolumes VirtualDiskFlag = 0x00000200
|
OpenVirtualDiskFlagSupportCompressedVolumes VirtualDiskFlag = 0x00000200
|
||||||
|
|
||||||
// Flags for attaching a VHD
|
// Flags for attaching a VHD.
|
||||||
AttachVirtualDiskFlagNone AttachVirtualDiskFlag = 0x00000000
|
AttachVirtualDiskFlagNone AttachVirtualDiskFlag = 0x00000000
|
||||||
AttachVirtualDiskFlagReadOnly AttachVirtualDiskFlag = 0x00000001
|
AttachVirtualDiskFlagReadOnly AttachVirtualDiskFlag = 0x00000001
|
||||||
AttachVirtualDiskFlagNoDriveLetter AttachVirtualDiskFlag = 0x00000002
|
AttachVirtualDiskFlagNoDriveLetter AttachVirtualDiskFlag = 0x00000002
|
||||||
@ -140,12 +141,14 @@ const (
|
|||||||
AttachVirtualDiskFlagSinglePartition AttachVirtualDiskFlag = 0x00000100
|
AttachVirtualDiskFlagSinglePartition AttachVirtualDiskFlag = 0x00000100
|
||||||
AttachVirtualDiskFlagRegisterVolume AttachVirtualDiskFlag = 0x00000200
|
AttachVirtualDiskFlagRegisterVolume AttachVirtualDiskFlag = 0x00000200
|
||||||
|
|
||||||
// Flags for detaching a VHD
|
// Flags for detaching a VHD.
|
||||||
DetachVirtualDiskFlagNone DetachVirtualDiskFlag = 0x0
|
DetachVirtualDiskFlagNone DetachVirtualDiskFlag = 0x0
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateVhdx is a helper function to create a simple vhdx file at the given path using
|
// CreateVhdx is a helper function to create a simple vhdx file at the given path using
|
||||||
// default values.
|
// default values.
|
||||||
|
//
|
||||||
|
//revive:disable-next-line:var-naming VHDX, not Vhdx
|
||||||
func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {
|
func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {
|
||||||
params := CreateVirtualDiskParameters{
|
params := CreateVirtualDiskParameters{
|
||||||
Version: 2,
|
Version: 2,
|
||||||
@ -172,6 +175,8 @@ func DetachVirtualDisk(handle syscall.Handle) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DetachVhd detaches a vhd found at `path`.
|
// DetachVhd detaches a vhd found at `path`.
|
||||||
|
//
|
||||||
|
//revive:disable-next-line:var-naming VHD, not Vhd
|
||||||
func DetachVhd(path string) error {
|
func DetachVhd(path string) error {
|
||||||
handle, err := OpenVirtualDisk(
|
handle, err := OpenVirtualDisk(
|
||||||
path,
|
path,
|
||||||
@ -181,12 +186,16 @@ func DetachVhd(path string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer syscall.CloseHandle(handle)
|
defer syscall.CloseHandle(handle) //nolint:errcheck
|
||||||
return DetachVirtualDisk(handle)
|
return DetachVirtualDisk(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AttachVirtualDisk attaches a virtual hard disk for use.
|
// AttachVirtualDisk attaches a virtual hard disk for use.
|
||||||
func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtualDiskFlag, parameters *AttachVirtualDiskParameters) (err error) {
|
func AttachVirtualDisk(
|
||||||
|
handle syscall.Handle,
|
||||||
|
attachVirtualDiskFlag AttachVirtualDiskFlag,
|
||||||
|
parameters *AttachVirtualDiskParameters,
|
||||||
|
) (err error) {
|
||||||
// Supports both version 1 and 2 of the attach parameters as version 2 wasn't present in RS5.
|
// Supports both version 1 and 2 of the attach parameters as version 2 wasn't present in RS5.
|
||||||
if err := attachVirtualDisk(
|
if err := attachVirtualDisk(
|
||||||
handle,
|
handle,
|
||||||
@ -203,6 +212,8 @@ func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtua
|
|||||||
|
|
||||||
// AttachVhd attaches a virtual hard disk at `path` for use. Attaches using version 2
|
// AttachVhd attaches a virtual hard disk at `path` for use. Attaches using version 2
|
||||||
// of the ATTACH_VIRTUAL_DISK_PARAMETERS.
|
// of the ATTACH_VIRTUAL_DISK_PARAMETERS.
|
||||||
|
//
|
||||||
|
//revive:disable-next-line:var-naming VHD, not Vhd
|
||||||
func AttachVhd(path string) (err error) {
|
func AttachVhd(path string) (err error) {
|
||||||
handle, err := OpenVirtualDisk(
|
handle, err := OpenVirtualDisk(
|
||||||
path,
|
path,
|
||||||
@ -213,7 +224,7 @@ func AttachVhd(path string) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer syscall.CloseHandle(handle)
|
defer syscall.CloseHandle(handle) //nolint:errcheck
|
||||||
params := AttachVirtualDiskParameters{Version: 2}
|
params := AttachVirtualDiskParameters{Version: 2}
|
||||||
if err := AttachVirtualDisk(
|
if err := AttachVirtualDisk(
|
||||||
handle,
|
handle,
|
||||||
@ -226,7 +237,11 @@ func AttachVhd(path string) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags.
|
// OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags.
|
||||||
func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag) (syscall.Handle, error) {
|
func OpenVirtualDisk(
|
||||||
|
vhdPath string,
|
||||||
|
virtualDiskAccessMask VirtualDiskAccessMask,
|
||||||
|
openVirtualDiskFlags VirtualDiskFlag,
|
||||||
|
) (syscall.Handle, error) {
|
||||||
parameters := OpenVirtualDiskParameters{Version: 2}
|
parameters := OpenVirtualDiskParameters{Version: 2}
|
||||||
handle, err := OpenVirtualDiskWithParameters(
|
handle, err := OpenVirtualDiskWithParameters(
|
||||||
vhdPath,
|
vhdPath,
|
||||||
@ -241,7 +256,12 @@ func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OpenVirtualDiskWithParameters obtains a handle to a VHD opened with supplied access mask, flags and parameters.
|
// OpenVirtualDiskWithParameters obtains a handle to a VHD opened with supplied access mask, flags and parameters.
|
||||||
func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag, parameters *OpenVirtualDiskParameters) (syscall.Handle, error) {
|
func OpenVirtualDiskWithParameters(
|
||||||
|
vhdPath string,
|
||||||
|
virtualDiskAccessMask VirtualDiskAccessMask,
|
||||||
|
openVirtualDiskFlags VirtualDiskFlag,
|
||||||
|
parameters *OpenVirtualDiskParameters,
|
||||||
|
) (syscall.Handle, error) {
|
||||||
var (
|
var (
|
||||||
handle syscall.Handle
|
handle syscall.Handle
|
||||||
defaultType VirtualStorageType
|
defaultType VirtualStorageType
|
||||||
@ -279,7 +299,12 @@ func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask Virtual
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateVirtualDisk creates a virtual harddisk and returns a handle to the disk.
|
// CreateVirtualDisk creates a virtual harddisk and returns a handle to the disk.
|
||||||
func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, createVirtualDiskFlags CreateVirtualDiskFlag, parameters *CreateVirtualDiskParameters) (syscall.Handle, error) {
|
func CreateVirtualDisk(
|
||||||
|
path string,
|
||||||
|
virtualDiskAccessMask VirtualDiskAccessMask,
|
||||||
|
createVirtualDiskFlags CreateVirtualDiskFlag,
|
||||||
|
parameters *CreateVirtualDiskParameters,
|
||||||
|
) (syscall.Handle, error) {
|
||||||
var (
|
var (
|
||||||
handle syscall.Handle
|
handle syscall.Handle
|
||||||
defaultType VirtualStorageType
|
defaultType VirtualStorageType
|
||||||
@ -323,6 +348,8 @@ func GetVirtualDiskPhysicalPath(handle syscall.Handle) (_ string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateDiffVhd is a helper function to create a differencing virtual disk.
|
// CreateDiffVhd is a helper function to create a differencing virtual disk.
|
||||||
|
//
|
||||||
|
//revive:disable-next-line:var-naming VHD, not Vhd
|
||||||
func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error {
|
func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error {
|
||||||
// Setting `ParentPath` is how to signal to create a differencing disk.
|
// Setting `ParentPath` is how to signal to create a differencing disk.
|
||||||
createParams := &CreateVirtualDiskParameters{
|
createParams := &CreateVirtualDiskParameters{
|
||||||
|
4
vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go
generated
vendored
4
vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go
generated
vendored
@ -1,4 +1,6 @@
|
|||||||
// Code generated by 'go generate'; DO NOT EDIT.
|
//go:build windows
|
||||||
|
|
||||||
|
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
|
||||||
|
|
||||||
package vhd
|
package vhd
|
||||||
|
|
||||||
|
45
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
45
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
@ -1,4 +1,6 @@
|
|||||||
// Code generated by 'go generate'; DO NOT EDIT.
|
//go:build windows
|
||||||
|
|
||||||
|
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
|
||||||
|
|
||||||
package winio
|
package winio
|
||||||
|
|
||||||
@ -47,9 +49,11 @@ var (
|
|||||||
procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
|
procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
|
||||||
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
|
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
|
||||||
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
||||||
|
procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW")
|
||||||
procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength")
|
procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength")
|
||||||
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
|
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
|
||||||
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
||||||
|
procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW")
|
||||||
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
|
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
|
||||||
procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW")
|
procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW")
|
||||||
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
|
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
|
||||||
@ -74,7 +78,6 @@ var (
|
|||||||
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
|
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
|
||||||
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
||||||
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult")
|
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult")
|
||||||
procbind = modws2_32.NewProc("bind")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
|
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
|
||||||
@ -123,6 +126,14 @@ func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertStringSidToSid(str *uint16, sid **byte) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid)), 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func getSecurityDescriptorLength(sd uintptr) (len uint32) {
|
func getSecurityDescriptorLength(sd uintptr) (len uint32) {
|
||||||
r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
|
r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
|
||||||
len = uint32(r0)
|
len = uint32(r0)
|
||||||
@ -154,6 +165,14 @@ func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidS
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
|
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
|
||||||
var _p0 *uint16
|
var _p0 *uint16
|
||||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||||
@ -380,25 +399,25 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro
|
|||||||
return
|
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) {
|
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)
|
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)
|
status = ntStatus(r0)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) {
|
func rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) {
|
||||||
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
|
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
|
||||||
status = ntstatus(r0)
|
status = ntStatus(r0)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) {
|
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)
|
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
|
||||||
status = ntstatus(r0)
|
status = ntStatus(r0)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func rtlNtStatusToDosError(status ntstatus) (winerr error) {
|
func rtlNtStatusToDosError(status ntStatus) (winerr error) {
|
||||||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
||||||
if r0 != 0 {
|
if r0 != 0 {
|
||||||
winerr = syscall.Errno(r0)
|
winerr = syscall.Errno(r0)
|
||||||
@ -417,11 +436,3 @@ func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint
|
|||||||
}
|
}
|
||||||
return
|
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 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
27
vendor/golang.org/x/mod/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/mod/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22
vendor/golang.org/x/mod/PATENTS
generated
vendored
Normal file
22
vendor/golang.org/x/mod/PATENTS
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
Additional IP Rights Grant (Patents)
|
||||||
|
|
||||||
|
"This implementation" means the copyrightable works distributed by
|
||||||
|
Google as part of the Go project.
|
||||||
|
|
||||||
|
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||||
|
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||||
|
patent license to make, have made, use, offer to sell, sell, import,
|
||||||
|
transfer and otherwise run, modify and propagate the contents of this
|
||||||
|
implementation of Go, where such license applies only to those patent
|
||||||
|
claims, both currently owned or controlled by Google and acquired in
|
||||||
|
the future, licensable by Google that are necessarily infringed by this
|
||||||
|
implementation of Go. This grant does not include claims that would be
|
||||||
|
infringed only as a consequence of further modification of this
|
||||||
|
implementation. If you or your agent or exclusive licensee institute or
|
||||||
|
order or agree to the institution of patent litigation against any
|
||||||
|
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||||
|
that this implementation of Go or any code incorporated within this
|
||||||
|
implementation of Go constitutes direct or contributory patent
|
||||||
|
infringement, or inducement of patent infringement, then any patent
|
||||||
|
rights granted to you under this License for this implementation of Go
|
||||||
|
shall terminate as of the date such litigation is filed.
|
401
vendor/golang.org/x/mod/semver/semver.go
generated
vendored
Normal file
401
vendor/golang.org/x/mod/semver/semver.go
generated
vendored
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package semver implements comparison of semantic version strings.
|
||||||
|
// In this package, semantic version strings must begin with a leading "v",
|
||||||
|
// as in "v1.0.0".
|
||||||
|
//
|
||||||
|
// The general form of a semantic version string accepted by this package is
|
||||||
|
//
|
||||||
|
// vMAJOR[.MINOR[.PATCH[-PRERELEASE][+BUILD]]]
|
||||||
|
//
|
||||||
|
// where square brackets indicate optional parts of the syntax;
|
||||||
|
// MAJOR, MINOR, and PATCH are decimal integers without extra leading zeros;
|
||||||
|
// PRERELEASE and BUILD are each a series of non-empty dot-separated identifiers
|
||||||
|
// using only alphanumeric characters and hyphens; and
|
||||||
|
// all-numeric PRERELEASE identifiers must not have leading zeros.
|
||||||
|
//
|
||||||
|
// This package follows Semantic Versioning 2.0.0 (see semver.org)
|
||||||
|
// with two exceptions. First, it requires the "v" prefix. Second, it recognizes
|
||||||
|
// vMAJOR and vMAJOR.MINOR (with no prerelease or build suffixes)
|
||||||
|
// as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0.
|
||||||
|
package semver
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
|
// parsed returns the parsed form of a semantic version string.
|
||||||
|
type parsed struct {
|
||||||
|
major string
|
||||||
|
minor string
|
||||||
|
patch string
|
||||||
|
short string
|
||||||
|
prerelease string
|
||||||
|
build string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValid reports whether v is a valid semantic version string.
|
||||||
|
func IsValid(v string) bool {
|
||||||
|
_, ok := parse(v)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Canonical returns the canonical formatting of the semantic version v.
|
||||||
|
// It fills in any missing .MINOR or .PATCH and discards build metadata.
|
||||||
|
// Two semantic versions compare equal only if their canonical formattings
|
||||||
|
// are identical strings.
|
||||||
|
// The canonical invalid semantic version is the empty string.
|
||||||
|
func Canonical(v string) string {
|
||||||
|
p, ok := parse(v)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if p.build != "" {
|
||||||
|
return v[:len(v)-len(p.build)]
|
||||||
|
}
|
||||||
|
if p.short != "" {
|
||||||
|
return v + p.short
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Major returns the major version prefix of the semantic version v.
|
||||||
|
// For example, Major("v2.1.0") == "v2".
|
||||||
|
// If v is an invalid semantic version string, Major returns the empty string.
|
||||||
|
func Major(v string) string {
|
||||||
|
pv, ok := parse(v)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return v[:1+len(pv.major)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MajorMinor returns the major.minor version prefix of the semantic version v.
|
||||||
|
// For example, MajorMinor("v2.1.0") == "v2.1".
|
||||||
|
// If v is an invalid semantic version string, MajorMinor returns the empty string.
|
||||||
|
func MajorMinor(v string) string {
|
||||||
|
pv, ok := parse(v)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
i := 1 + len(pv.major)
|
||||||
|
if j := i + 1 + len(pv.minor); j <= len(v) && v[i] == '.' && v[i+1:j] == pv.minor {
|
||||||
|
return v[:j]
|
||||||
|
}
|
||||||
|
return v[:i] + "." + pv.minor
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prerelease returns the prerelease suffix of the semantic version v.
|
||||||
|
// For example, Prerelease("v2.1.0-pre+meta") == "-pre".
|
||||||
|
// If v is an invalid semantic version string, Prerelease returns the empty string.
|
||||||
|
func Prerelease(v string) string {
|
||||||
|
pv, ok := parse(v)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return pv.prerelease
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build returns the build suffix of the semantic version v.
|
||||||
|
// For example, Build("v2.1.0+meta") == "+meta".
|
||||||
|
// If v is an invalid semantic version string, Build returns the empty string.
|
||||||
|
func Build(v string) string {
|
||||||
|
pv, ok := parse(v)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return pv.build
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare returns an integer comparing two versions according to
|
||||||
|
// semantic version precedence.
|
||||||
|
// The result will be 0 if v == w, -1 if v < w, or +1 if v > w.
|
||||||
|
//
|
||||||
|
// An invalid semantic version string is considered less than a valid one.
|
||||||
|
// All invalid semantic version strings compare equal to each other.
|
||||||
|
func Compare(v, w string) int {
|
||||||
|
pv, ok1 := parse(v)
|
||||||
|
pw, ok2 := parse(w)
|
||||||
|
if !ok1 && !ok2 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if !ok1 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if !ok2 {
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
if c := compareInt(pv.major, pw.major); c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
if c := compareInt(pv.minor, pw.minor); c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
if c := compareInt(pv.patch, pw.patch); c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return comparePrerelease(pv.prerelease, pw.prerelease)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max canonicalizes its arguments and then returns the version string
|
||||||
|
// that compares greater.
|
||||||
|
//
|
||||||
|
// Deprecated: use Compare instead. In most cases, returning a canonicalized
|
||||||
|
// version is not expected or desired.
|
||||||
|
func Max(v, w string) string {
|
||||||
|
v = Canonical(v)
|
||||||
|
w = Canonical(w)
|
||||||
|
if Compare(v, w) > 0 {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByVersion implements sort.Interface for sorting semantic version strings.
|
||||||
|
type ByVersion []string
|
||||||
|
|
||||||
|
func (vs ByVersion) Len() int { return len(vs) }
|
||||||
|
func (vs ByVersion) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
|
||||||
|
func (vs ByVersion) Less(i, j int) bool {
|
||||||
|
cmp := Compare(vs[i], vs[j])
|
||||||
|
if cmp != 0 {
|
||||||
|
return cmp < 0
|
||||||
|
}
|
||||||
|
return vs[i] < vs[j]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort sorts a list of semantic version strings using ByVersion.
|
||||||
|
func Sort(list []string) {
|
||||||
|
sort.Sort(ByVersion(list))
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse(v string) (p parsed, ok bool) {
|
||||||
|
if v == "" || v[0] != 'v' {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.major, v, ok = parseInt(v[1:])
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v == "" {
|
||||||
|
p.minor = "0"
|
||||||
|
p.patch = "0"
|
||||||
|
p.short = ".0.0"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v[0] != '.' {
|
||||||
|
ok = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.minor, v, ok = parseInt(v[1:])
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v == "" {
|
||||||
|
p.patch = "0"
|
||||||
|
p.short = ".0"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v[0] != '.' {
|
||||||
|
ok = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.patch, v, ok = parseInt(v[1:])
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(v) > 0 && v[0] == '-' {
|
||||||
|
p.prerelease, v, ok = parsePrerelease(v)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(v) > 0 && v[0] == '+' {
|
||||||
|
p.build, v, ok = parseBuild(v)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v != "" {
|
||||||
|
ok = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ok = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInt(v string) (t, rest string, ok bool) {
|
||||||
|
if v == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v[0] < '0' || '9' < v[0] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i := 1
|
||||||
|
for i < len(v) && '0' <= v[i] && v[i] <= '9' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if v[0] == '0' && i != 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return v[:i], v[i:], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func parsePrerelease(v string) (t, rest string, ok bool) {
|
||||||
|
// "A pre-release version MAY be denoted by appending a hyphen and
|
||||||
|
// a series of dot separated identifiers immediately following the patch version.
|
||||||
|
// Identifiers MUST comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-].
|
||||||
|
// Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes."
|
||||||
|
if v == "" || v[0] != '-' {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i := 1
|
||||||
|
start := 1
|
||||||
|
for i < len(v) && v[i] != '+' {
|
||||||
|
if !isIdentChar(v[i]) && v[i] != '.' {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v[i] == '.' {
|
||||||
|
if start == i || isBadNum(v[start:i]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
start = i + 1
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if start == i || isBadNum(v[start:i]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return v[:i], v[i:], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBuild(v string) (t, rest string, ok bool) {
|
||||||
|
if v == "" || v[0] != '+' {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i := 1
|
||||||
|
start := 1
|
||||||
|
for i < len(v) {
|
||||||
|
if !isIdentChar(v[i]) && v[i] != '.' {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v[i] == '.' {
|
||||||
|
if start == i {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
start = i + 1
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if start == i {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return v[:i], v[i:], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isIdentChar(c byte) bool {
|
||||||
|
return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBadNum(v string) bool {
|
||||||
|
i := 0
|
||||||
|
for i < len(v) && '0' <= v[i] && v[i] <= '9' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return i == len(v) && i > 1 && v[0] == '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNum(v string) bool {
|
||||||
|
i := 0
|
||||||
|
for i < len(v) && '0' <= v[i] && v[i] <= '9' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return i == len(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func compareInt(x, y string) int {
|
||||||
|
if x == y {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if len(x) < len(y) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if len(x) > len(y) {
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
if x < y {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func comparePrerelease(x, y string) int {
|
||||||
|
// "When major, minor, and patch are equal, a pre-release version has
|
||||||
|
// lower precedence than a normal version.
|
||||||
|
// Example: 1.0.0-alpha < 1.0.0.
|
||||||
|
// Precedence for two pre-release versions with the same major, minor,
|
||||||
|
// and patch version MUST be determined by comparing each dot separated
|
||||||
|
// identifier from left to right until a difference is found as follows:
|
||||||
|
// identifiers consisting of only digits are compared numerically and
|
||||||
|
// identifiers with letters or hyphens are compared lexically in ASCII
|
||||||
|
// sort order. Numeric identifiers always have lower precedence than
|
||||||
|
// non-numeric identifiers. A larger set of pre-release fields has a
|
||||||
|
// higher precedence than a smaller set, if all of the preceding
|
||||||
|
// identifiers are equal.
|
||||||
|
// Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta <
|
||||||
|
// 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0."
|
||||||
|
if x == y {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if x == "" {
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
if y == "" {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
for x != "" && y != "" {
|
||||||
|
x = x[1:] // skip - or .
|
||||||
|
y = y[1:] // skip - or .
|
||||||
|
var dx, dy string
|
||||||
|
dx, x = nextIdent(x)
|
||||||
|
dy, y = nextIdent(y)
|
||||||
|
if dx != dy {
|
||||||
|
ix := isNum(dx)
|
||||||
|
iy := isNum(dy)
|
||||||
|
if ix != iy {
|
||||||
|
if ix {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ix {
|
||||||
|
if len(dx) < len(dy) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if len(dx) > len(dy) {
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dx < dy {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if x == "" {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nextIdent(x string) (dx, rest string) {
|
||||||
|
i := 0
|
||||||
|
for i < len(x) && x[i] != '.' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return x[:i], x[i:]
|
||||||
|
}
|
27
vendor/golang.org/x/tools/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/tools/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22
vendor/golang.org/x/tools/PATENTS
generated
vendored
Normal file
22
vendor/golang.org/x/tools/PATENTS
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
Additional IP Rights Grant (Patents)
|
||||||
|
|
||||||
|
"This implementation" means the copyrightable works distributed by
|
||||||
|
Google as part of the Go project.
|
||||||
|
|
||||||
|
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||||
|
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||||
|
patent license to make, have made, use, offer to sell, sell, import,
|
||||||
|
transfer and otherwise run, modify and propagate the contents of this
|
||||||
|
implementation of Go, where such license applies only to those patent
|
||||||
|
claims, both currently owned or controlled by Google and acquired in
|
||||||
|
the future, licensable by Google that are necessarily infringed by this
|
||||||
|
implementation of Go. This grant does not include claims that would be
|
||||||
|
infringed only as a consequence of further modification of this
|
||||||
|
implementation. If you or your agent or exclusive licensee institute or
|
||||||
|
order or agree to the institution of patent litigation against any
|
||||||
|
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||||
|
that this implementation of Go or any code incorporated within this
|
||||||
|
implementation of Go constitutes direct or contributory patent
|
||||||
|
infringement, or inducement of patent infringement, then any patent
|
||||||
|
rights granted to you under this License for this implementation of Go
|
||||||
|
shall terminate as of the date such litigation is filed.
|
658
vendor/golang.org/x/tools/cmd/stringer/stringer.go
generated
vendored
Normal file
658
vendor/golang.org/x/tools/cmd/stringer/stringer.go
generated
vendored
Normal file
@ -0,0 +1,658 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer
|
||||||
|
// interface. Given the name of a (signed or unsigned) integer type T that has constants
|
||||||
|
// defined, stringer will create a new self-contained Go source file implementing
|
||||||
|
//
|
||||||
|
// func (t T) String() string
|
||||||
|
//
|
||||||
|
// The file is created in the same package and directory as the package that defines T.
|
||||||
|
// It has helpful defaults designed for use with go generate.
|
||||||
|
//
|
||||||
|
// Stringer works best with constants that are consecutive values such as created using iota,
|
||||||
|
// but creates good code regardless. In the future it might also provide custom support for
|
||||||
|
// constant sets that are bit patterns.
|
||||||
|
//
|
||||||
|
// For example, given this snippet,
|
||||||
|
//
|
||||||
|
// package painkiller
|
||||||
|
//
|
||||||
|
// type Pill int
|
||||||
|
//
|
||||||
|
// const (
|
||||||
|
// Placebo Pill = iota
|
||||||
|
// Aspirin
|
||||||
|
// Ibuprofen
|
||||||
|
// Paracetamol
|
||||||
|
// Acetaminophen = Paracetamol
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// running this command
|
||||||
|
//
|
||||||
|
// stringer -type=Pill
|
||||||
|
//
|
||||||
|
// in the same directory will create the file pill_string.go, in package painkiller,
|
||||||
|
// containing a definition of
|
||||||
|
//
|
||||||
|
// func (Pill) String() string
|
||||||
|
//
|
||||||
|
// That method will translate the value of a Pill constant to the string representation
|
||||||
|
// of the respective constant name, so that the call fmt.Print(painkiller.Aspirin) will
|
||||||
|
// print the string "Aspirin".
|
||||||
|
//
|
||||||
|
// Typically this process would be run using go generate, like this:
|
||||||
|
//
|
||||||
|
// //go:generate stringer -type=Pill
|
||||||
|
//
|
||||||
|
// If multiple constants have the same value, the lexically first matching name will
|
||||||
|
// be used (in the example, Acetaminophen will print as "Paracetamol").
|
||||||
|
//
|
||||||
|
// With no arguments, it processes the package in the current directory.
|
||||||
|
// Otherwise, the arguments must name a single directory holding a Go package
|
||||||
|
// or a set of Go source files that represent a single Go package.
|
||||||
|
//
|
||||||
|
// The -type flag accepts a comma-separated list of types so a single run can
|
||||||
|
// generate methods for multiple types. The default output file is t_string.go,
|
||||||
|
// where t is the lower-cased name of the first type listed. It can be overridden
|
||||||
|
// with the -output flag.
|
||||||
|
//
|
||||||
|
// The -linecomment flag tells stringer to generate the text of any line comment, trimmed
|
||||||
|
// of leading spaces, instead of the constant name. For instance, if the constants above had a
|
||||||
|
// Pill prefix, one could write
|
||||||
|
//
|
||||||
|
// PillAspirin // Aspirin
|
||||||
|
//
|
||||||
|
// to suppress it in the output.
|
||||||
|
package main // import "golang.org/x/tools/cmd/stringer"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/constant"
|
||||||
|
"go/format"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
typeNames = flag.String("type", "", "comma-separated list of type names; must be set")
|
||||||
|
output = flag.String("output", "", "output file name; default srcdir/<type>_string.go")
|
||||||
|
trimprefix = flag.String("trimprefix", "", "trim the `prefix` from the generated constant names")
|
||||||
|
linecomment = flag.Bool("linecomment", false, "use line comment text as printed text when present")
|
||||||
|
buildTags = flag.String("tags", "", "comma-separated list of build tags to apply")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Usage is a replacement usage function for the flags package.
|
||||||
|
func Usage() {
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage of stringer:\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T [directory]\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T files... # Must be a single package\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "For more information, see:\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "\thttps://pkg.go.dev/golang.org/x/tools/cmd/stringer\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Flags:\n")
|
||||||
|
flag.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.SetFlags(0)
|
||||||
|
log.SetPrefix("stringer: ")
|
||||||
|
flag.Usage = Usage
|
||||||
|
flag.Parse()
|
||||||
|
if len(*typeNames) == 0 {
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
types := strings.Split(*typeNames, ",")
|
||||||
|
var tags []string
|
||||||
|
if len(*buildTags) > 0 {
|
||||||
|
tags = strings.Split(*buildTags, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
// We accept either one directory or a list of files. Which do we have?
|
||||||
|
args := flag.Args()
|
||||||
|
if len(args) == 0 {
|
||||||
|
// Default: process whole package in current directory.
|
||||||
|
args = []string{"."}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the package once.
|
||||||
|
var dir string
|
||||||
|
g := Generator{
|
||||||
|
trimPrefix: *trimprefix,
|
||||||
|
lineComment: *linecomment,
|
||||||
|
}
|
||||||
|
// TODO(suzmue): accept other patterns for packages (directories, list of files, import paths, etc).
|
||||||
|
if len(args) == 1 && isDirectory(args[0]) {
|
||||||
|
dir = args[0]
|
||||||
|
} else {
|
||||||
|
if len(tags) != 0 {
|
||||||
|
log.Fatal("-tags option applies only to directories, not when files are specified")
|
||||||
|
}
|
||||||
|
dir = filepath.Dir(args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
g.parsePackage(args, tags)
|
||||||
|
|
||||||
|
// Print the header and package clause.
|
||||||
|
g.Printf("// Code generated by \"stringer %s\"; DO NOT EDIT.\n", strings.Join(os.Args[1:], " "))
|
||||||
|
g.Printf("\n")
|
||||||
|
g.Printf("package %s", g.pkg.name)
|
||||||
|
g.Printf("\n")
|
||||||
|
g.Printf("import \"strconv\"\n") // Used by all methods.
|
||||||
|
|
||||||
|
// Run generate for each type.
|
||||||
|
for _, typeName := range types {
|
||||||
|
g.generate(typeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the output.
|
||||||
|
src := g.format()
|
||||||
|
|
||||||
|
// Write to file.
|
||||||
|
outputName := *output
|
||||||
|
if outputName == "" {
|
||||||
|
baseName := fmt.Sprintf("%s_string.go", types[0])
|
||||||
|
outputName = filepath.Join(dir, strings.ToLower(baseName))
|
||||||
|
}
|
||||||
|
err := ioutil.WriteFile(outputName, src, 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("writing output: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// isDirectory reports whether the named file is a directory.
|
||||||
|
func isDirectory(name string) bool {
|
||||||
|
info, err := os.Stat(name)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return info.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generator holds the state of the analysis. Primarily used to buffer
|
||||||
|
// the output for format.Source.
|
||||||
|
type Generator struct {
|
||||||
|
buf bytes.Buffer // Accumulated output.
|
||||||
|
pkg *Package // Package we are scanning.
|
||||||
|
|
||||||
|
trimPrefix string
|
||||||
|
lineComment bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Generator) Printf(format string, args ...interface{}) {
|
||||||
|
fmt.Fprintf(&g.buf, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// File holds a single parsed file and associated data.
|
||||||
|
type File struct {
|
||||||
|
pkg *Package // Package to which this file belongs.
|
||||||
|
file *ast.File // Parsed AST.
|
||||||
|
// These fields are reset for each type being generated.
|
||||||
|
typeName string // Name of the constant type.
|
||||||
|
values []Value // Accumulator for constant values of that type.
|
||||||
|
|
||||||
|
trimPrefix string
|
||||||
|
lineComment bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Package struct {
|
||||||
|
name string
|
||||||
|
defs map[*ast.Ident]types.Object
|
||||||
|
files []*File
|
||||||
|
}
|
||||||
|
|
||||||
|
// parsePackage analyzes the single package constructed from the patterns and tags.
|
||||||
|
// parsePackage exits if there is an error.
|
||||||
|
func (g *Generator) parsePackage(patterns []string, tags []string) {
|
||||||
|
cfg := &packages.Config{
|
||||||
|
Mode: packages.NeedName | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax,
|
||||||
|
// TODO: Need to think about constants in test files. Maybe write type_string_test.go
|
||||||
|
// in a separate pass? For later.
|
||||||
|
Tests: false,
|
||||||
|
BuildFlags: []string{fmt.Sprintf("-tags=%s", strings.Join(tags, " "))},
|
||||||
|
}
|
||||||
|
pkgs, err := packages.Load(cfg, patterns...)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(pkgs) != 1 {
|
||||||
|
log.Fatalf("error: %d packages found", len(pkgs))
|
||||||
|
}
|
||||||
|
g.addPackage(pkgs[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// addPackage adds a type checked Package and its syntax files to the generator.
|
||||||
|
func (g *Generator) addPackage(pkg *packages.Package) {
|
||||||
|
g.pkg = &Package{
|
||||||
|
name: pkg.Name,
|
||||||
|
defs: pkg.TypesInfo.Defs,
|
||||||
|
files: make([]*File, len(pkg.Syntax)),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, file := range pkg.Syntax {
|
||||||
|
g.pkg.files[i] = &File{
|
||||||
|
file: file,
|
||||||
|
pkg: g.pkg,
|
||||||
|
trimPrefix: g.trimPrefix,
|
||||||
|
lineComment: g.lineComment,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate produces the String method for the named type.
|
||||||
|
func (g *Generator) generate(typeName string) {
|
||||||
|
values := make([]Value, 0, 100)
|
||||||
|
for _, file := range g.pkg.files {
|
||||||
|
// Set the state for this run of the walker.
|
||||||
|
file.typeName = typeName
|
||||||
|
file.values = nil
|
||||||
|
if file.file != nil {
|
||||||
|
ast.Inspect(file.file, file.genDecl)
|
||||||
|
values = append(values, file.values...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(values) == 0 {
|
||||||
|
log.Fatalf("no values defined for type %s", typeName)
|
||||||
|
}
|
||||||
|
// Generate code that will fail if the constants change value.
|
||||||
|
g.Printf("func _() {\n")
|
||||||
|
g.Printf("\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n")
|
||||||
|
g.Printf("\t// Re-run the stringer command to generate them again.\n")
|
||||||
|
g.Printf("\tvar x [1]struct{}\n")
|
||||||
|
for _, v := range values {
|
||||||
|
g.Printf("\t_ = x[%s - %s]\n", v.originalName, v.str)
|
||||||
|
}
|
||||||
|
g.Printf("}\n")
|
||||||
|
runs := splitIntoRuns(values)
|
||||||
|
// The decision of which pattern to use depends on the number of
|
||||||
|
// runs in the numbers. If there's only one, it's easy. For more than
|
||||||
|
// one, there's a tradeoff between complexity and size of the data
|
||||||
|
// and code vs. the simplicity of a map. A map takes more space,
|
||||||
|
// but so does the code. The decision here (crossover at 10) is
|
||||||
|
// arbitrary, but considers that for large numbers of runs the cost
|
||||||
|
// of the linear scan in the switch might become important, and
|
||||||
|
// rather than use yet another algorithm such as binary search,
|
||||||
|
// we punt and use a map. In any case, the likelihood of a map
|
||||||
|
// being necessary for any realistic example other than bitmasks
|
||||||
|
// is very low. And bitmasks probably deserve their own analysis,
|
||||||
|
// to be done some other day.
|
||||||
|
switch {
|
||||||
|
case len(runs) == 1:
|
||||||
|
g.buildOneRun(runs, typeName)
|
||||||
|
case len(runs) <= 10:
|
||||||
|
g.buildMultipleRuns(runs, typeName)
|
||||||
|
default:
|
||||||
|
g.buildMap(runs, typeName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// splitIntoRuns breaks the values into runs of contiguous sequences.
|
||||||
|
// For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}.
|
||||||
|
// The input slice is known to be non-empty.
|
||||||
|
func splitIntoRuns(values []Value) [][]Value {
|
||||||
|
// We use stable sort so the lexically first name is chosen for equal elements.
|
||||||
|
sort.Stable(byValue(values))
|
||||||
|
// Remove duplicates. Stable sort has put the one we want to print first,
|
||||||
|
// so use that one. The String method won't care about which named constant
|
||||||
|
// was the argument, so the first name for the given value is the only one to keep.
|
||||||
|
// We need to do this because identical values would cause the switch or map
|
||||||
|
// to fail to compile.
|
||||||
|
j := 1
|
||||||
|
for i := 1; i < len(values); i++ {
|
||||||
|
if values[i].value != values[i-1].value {
|
||||||
|
values[j] = values[i]
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
values = values[:j]
|
||||||
|
runs := make([][]Value, 0, 10)
|
||||||
|
for len(values) > 0 {
|
||||||
|
// One contiguous sequence per outer loop.
|
||||||
|
i := 1
|
||||||
|
for i < len(values) && values[i].value == values[i-1].value+1 {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
runs = append(runs, values[:i])
|
||||||
|
values = values[i:]
|
||||||
|
}
|
||||||
|
return runs
|
||||||
|
}
|
||||||
|
|
||||||
|
// format returns the gofmt-ed contents of the Generator's buffer.
|
||||||
|
func (g *Generator) format() []byte {
|
||||||
|
src, err := format.Source(g.buf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
// Should never happen, but can arise when developing this code.
|
||||||
|
// The user can compile the output to see the error.
|
||||||
|
log.Printf("warning: internal error: invalid Go generated: %s", err)
|
||||||
|
log.Printf("warning: compile the package to analyze the error")
|
||||||
|
return g.buf.Bytes()
|
||||||
|
}
|
||||||
|
return src
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value represents a declared constant.
|
||||||
|
type Value struct {
|
||||||
|
originalName string // The name of the constant.
|
||||||
|
name string // The name with trimmed prefix.
|
||||||
|
// The value is stored as a bit pattern alone. The boolean tells us
|
||||||
|
// whether to interpret it as an int64 or a uint64; the only place
|
||||||
|
// this matters is when sorting.
|
||||||
|
// Much of the time the str field is all we need; it is printed
|
||||||
|
// by Value.String.
|
||||||
|
value uint64 // Will be converted to int64 when needed.
|
||||||
|
signed bool // Whether the constant is a signed type.
|
||||||
|
str string // The string representation given by the "go/constant" package.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Value) String() string {
|
||||||
|
return v.str
|
||||||
|
}
|
||||||
|
|
||||||
|
// byValue lets us sort the constants into increasing order.
|
||||||
|
// We take care in the Less method to sort in signed or unsigned order,
|
||||||
|
// as appropriate.
|
||||||
|
type byValue []Value
|
||||||
|
|
||||||
|
func (b byValue) Len() int { return len(b) }
|
||||||
|
func (b byValue) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||||
|
func (b byValue) Less(i, j int) bool {
|
||||||
|
if b[i].signed {
|
||||||
|
return int64(b[i].value) < int64(b[j].value)
|
||||||
|
}
|
||||||
|
return b[i].value < b[j].value
|
||||||
|
}
|
||||||
|
|
||||||
|
// genDecl processes one declaration clause.
|
||||||
|
func (f *File) genDecl(node ast.Node) bool {
|
||||||
|
decl, ok := node.(*ast.GenDecl)
|
||||||
|
if !ok || decl.Tok != token.CONST {
|
||||||
|
// We only care about const declarations.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// The name of the type of the constants we are declaring.
|
||||||
|
// Can change if this is a multi-element declaration.
|
||||||
|
typ := ""
|
||||||
|
// Loop over the elements of the declaration. Each element is a ValueSpec:
|
||||||
|
// a list of names possibly followed by a type, possibly followed by values.
|
||||||
|
// If the type and value are both missing, we carry down the type (and value,
|
||||||
|
// but the "go/types" package takes care of that).
|
||||||
|
for _, spec := range decl.Specs {
|
||||||
|
vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST.
|
||||||
|
if vspec.Type == nil && len(vspec.Values) > 0 {
|
||||||
|
// "X = 1". With no type but a value. If the constant is untyped,
|
||||||
|
// skip this vspec and reset the remembered type.
|
||||||
|
typ = ""
|
||||||
|
|
||||||
|
// If this is a simple type conversion, remember the type.
|
||||||
|
// We don't mind if this is actually a call; a qualified call won't
|
||||||
|
// be matched (that will be SelectorExpr, not Ident), and only unusual
|
||||||
|
// situations will result in a function call that appears to be
|
||||||
|
// a type conversion.
|
||||||
|
ce, ok := vspec.Values[0].(*ast.CallExpr)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
id, ok := ce.Fun.(*ast.Ident)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
typ = id.Name
|
||||||
|
}
|
||||||
|
if vspec.Type != nil {
|
||||||
|
// "X T". We have a type. Remember it.
|
||||||
|
ident, ok := vspec.Type.(*ast.Ident)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
typ = ident.Name
|
||||||
|
}
|
||||||
|
if typ != f.typeName {
|
||||||
|
// This is not the type we're looking for.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// We now have a list of names (from one line of source code) all being
|
||||||
|
// declared with the desired type.
|
||||||
|
// Grab their names and actual values and store them in f.values.
|
||||||
|
for _, name := range vspec.Names {
|
||||||
|
if name.Name == "_" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// This dance lets the type checker find the values for us. It's a
|
||||||
|
// bit tricky: look up the object declared by the name, find its
|
||||||
|
// types.Const, and extract its value.
|
||||||
|
obj, ok := f.pkg.defs[name]
|
||||||
|
if !ok {
|
||||||
|
log.Fatalf("no value for constant %s", name)
|
||||||
|
}
|
||||||
|
info := obj.Type().Underlying().(*types.Basic).Info()
|
||||||
|
if info&types.IsInteger == 0 {
|
||||||
|
log.Fatalf("can't handle non-integer constant type %s", typ)
|
||||||
|
}
|
||||||
|
value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST.
|
||||||
|
if value.Kind() != constant.Int {
|
||||||
|
log.Fatalf("can't happen: constant is not an integer %s", name)
|
||||||
|
}
|
||||||
|
i64, isInt := constant.Int64Val(value)
|
||||||
|
u64, isUint := constant.Uint64Val(value)
|
||||||
|
if !isInt && !isUint {
|
||||||
|
log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String())
|
||||||
|
}
|
||||||
|
if !isInt {
|
||||||
|
u64 = uint64(i64)
|
||||||
|
}
|
||||||
|
v := Value{
|
||||||
|
originalName: name.Name,
|
||||||
|
value: u64,
|
||||||
|
signed: info&types.IsUnsigned == 0,
|
||||||
|
str: value.String(),
|
||||||
|
}
|
||||||
|
if c := vspec.Comment; f.lineComment && c != nil && len(c.List) == 1 {
|
||||||
|
v.name = strings.TrimSpace(c.Text())
|
||||||
|
} else {
|
||||||
|
v.name = strings.TrimPrefix(v.originalName, f.trimPrefix)
|
||||||
|
}
|
||||||
|
f.values = append(f.values, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
// usize returns the number of bits of the smallest unsigned integer
|
||||||
|
// type that will hold n. Used to create the smallest possible slice of
|
||||||
|
// integers to use as indexes into the concatenated strings.
|
||||||
|
func usize(n int) int {
|
||||||
|
switch {
|
||||||
|
case n < 1<<8:
|
||||||
|
return 8
|
||||||
|
case n < 1<<16:
|
||||||
|
return 16
|
||||||
|
default:
|
||||||
|
// 2^32 is enough constants for anyone.
|
||||||
|
return 32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// declareIndexAndNameVars declares the index slices and concatenated names
|
||||||
|
// strings representing the runs of values.
|
||||||
|
func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {
|
||||||
|
var indexes, names []string
|
||||||
|
for i, run := range runs {
|
||||||
|
index, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
|
||||||
|
if len(run) != 1 {
|
||||||
|
indexes = append(indexes, index)
|
||||||
|
}
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
g.Printf("const (\n")
|
||||||
|
for _, name := range names {
|
||||||
|
g.Printf("\t%s\n", name)
|
||||||
|
}
|
||||||
|
g.Printf(")\n\n")
|
||||||
|
|
||||||
|
if len(indexes) > 0 {
|
||||||
|
g.Printf("var (")
|
||||||
|
for _, index := range indexes {
|
||||||
|
g.Printf("\t%s\n", index)
|
||||||
|
}
|
||||||
|
g.Printf(")\n\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars
|
||||||
|
func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) {
|
||||||
|
index, name := g.createIndexAndNameDecl(run, typeName, "")
|
||||||
|
g.Printf("const %s\n", name)
|
||||||
|
g.Printf("var %s\n", index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var".
|
||||||
|
func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) {
|
||||||
|
b := new(bytes.Buffer)
|
||||||
|
indexes := make([]int, len(run))
|
||||||
|
for i := range run {
|
||||||
|
b.WriteString(run[i].name)
|
||||||
|
indexes[i] = b.Len()
|
||||||
|
}
|
||||||
|
nameConst := fmt.Sprintf("_%s_name%s = %q", typeName, suffix, b.String())
|
||||||
|
nameLen := b.Len()
|
||||||
|
b.Reset()
|
||||||
|
fmt.Fprintf(b, "_%s_index%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen))
|
||||||
|
for i, v := range indexes {
|
||||||
|
if i > 0 {
|
||||||
|
fmt.Fprintf(b, ", ")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "%d", v)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "}")
|
||||||
|
return b.String(), nameConst
|
||||||
|
}
|
||||||
|
|
||||||
|
// declareNameVars declares the concatenated names string representing all the values in the runs.
|
||||||
|
func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) {
|
||||||
|
g.Printf("const _%s_name%s = \"", typeName, suffix)
|
||||||
|
for _, run := range runs {
|
||||||
|
for i := range run {
|
||||||
|
g.Printf("%s", run[i].name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.Printf("\"\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildOneRun generates the variables and String method for a single run of contiguous values.
|
||||||
|
func (g *Generator) buildOneRun(runs [][]Value, typeName string) {
|
||||||
|
values := runs[0]
|
||||||
|
g.Printf("\n")
|
||||||
|
g.declareIndexAndNameVar(values, typeName)
|
||||||
|
// The generated code is simple enough to write as a Printf format.
|
||||||
|
lessThanZero := ""
|
||||||
|
if values[0].signed {
|
||||||
|
lessThanZero = "i < 0 || "
|
||||||
|
}
|
||||||
|
if values[0].value == 0 { // Signed or unsigned, 0 is still 0.
|
||||||
|
g.Printf(stringOneRun, typeName, usize(len(values)), lessThanZero)
|
||||||
|
} else {
|
||||||
|
g.Printf(stringOneRunWithOffset, typeName, values[0].String(), usize(len(values)), lessThanZero)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arguments to format are:
|
||||||
|
//
|
||||||
|
// [1]: type name
|
||||||
|
// [2]: size of index element (8 for uint8 etc.)
|
||||||
|
// [3]: less than zero check (for signed types)
|
||||||
|
const stringOneRun = `func (i %[1]s) String() string {
|
||||||
|
if %[3]si >= %[1]s(len(_%[1]s_index)-1) {
|
||||||
|
return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _%[1]s_name[_%[1]s_index[i]:_%[1]s_index[i+1]]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// Arguments to format are:
|
||||||
|
// [1]: type name
|
||||||
|
// [2]: lowest defined value for type, as a string
|
||||||
|
// [3]: size of index element (8 for uint8 etc.)
|
||||||
|
// [4]: less than zero check (for signed types)
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
const stringOneRunWithOffset = `func (i %[1]s) String() string {
|
||||||
|
i -= %[2]s
|
||||||
|
if %[4]si >= %[1]s(len(_%[1]s_index)-1) {
|
||||||
|
return "%[1]s(" + strconv.FormatInt(int64(i + %[2]s), 10) + ")"
|
||||||
|
}
|
||||||
|
return _%[1]s_name[_%[1]s_index[i] : _%[1]s_index[i+1]]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// buildMultipleRuns generates the variables and String method for multiple runs of contiguous values.
|
||||||
|
// For this pattern, a single Printf format won't do.
|
||||||
|
func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) {
|
||||||
|
g.Printf("\n")
|
||||||
|
g.declareIndexAndNameVars(runs, typeName)
|
||||||
|
g.Printf("func (i %s) String() string {\n", typeName)
|
||||||
|
g.Printf("\tswitch {\n")
|
||||||
|
for i, values := range runs {
|
||||||
|
if len(values) == 1 {
|
||||||
|
g.Printf("\tcase i == %s:\n", &values[0])
|
||||||
|
g.Printf("\t\treturn _%s_name_%d\n", typeName, i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if values[0].value == 0 && !values[0].signed {
|
||||||
|
// For an unsigned lower bound of 0, "0 <= i" would be redundant.
|
||||||
|
g.Printf("\tcase i <= %s:\n", &values[len(values)-1])
|
||||||
|
} else {
|
||||||
|
g.Printf("\tcase %s <= i && i <= %s:\n", &values[0], &values[len(values)-1])
|
||||||
|
}
|
||||||
|
if values[0].value != 0 {
|
||||||
|
g.Printf("\t\ti -= %s\n", &values[0])
|
||||||
|
}
|
||||||
|
g.Printf("\t\treturn _%s_name_%d[_%s_index_%d[i]:_%s_index_%d[i+1]]\n",
|
||||||
|
typeName, i, typeName, i, typeName, i)
|
||||||
|
}
|
||||||
|
g.Printf("\tdefault:\n")
|
||||||
|
g.Printf("\t\treturn \"%s(\" + strconv.FormatInt(int64(i), 10) + \")\"\n", typeName)
|
||||||
|
g.Printf("\t}\n")
|
||||||
|
g.Printf("}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildMap handles the case where the space is so sparse a map is a reasonable fallback.
|
||||||
|
// It's a rare situation but has simple code.
|
||||||
|
func (g *Generator) buildMap(runs [][]Value, typeName string) {
|
||||||
|
g.Printf("\n")
|
||||||
|
g.declareNameVars(runs, typeName, "")
|
||||||
|
g.Printf("\nvar _%s_map = map[%s]string{\n", typeName, typeName)
|
||||||
|
n := 0
|
||||||
|
for _, values := range runs {
|
||||||
|
for _, value := range values {
|
||||||
|
g.Printf("\t%s: _%s_name[%d:%d],\n", &value, typeName, n, n+len(value.name))
|
||||||
|
n += len(value.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.Printf("}\n\n")
|
||||||
|
g.Printf(stringMap, typeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Argument to format is the type name.
|
||||||
|
const stringMap = `func (i %[1]s) String() string {
|
||||||
|
if str, ok := _%[1]s_map[i]; ok {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
`
|
177
vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go
generated
vendored
Normal file
177
vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go
generated
vendored
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package gcexportdata provides functions for locating, reading, and
|
||||||
|
// writing export data files containing type information produced by the
|
||||||
|
// gc compiler. This package supports go1.7 export data format and all
|
||||||
|
// later versions.
|
||||||
|
//
|
||||||
|
// Although it might seem convenient for this package to live alongside
|
||||||
|
// go/types in the standard library, this would cause version skew
|
||||||
|
// problems for developer tools that use it, since they must be able to
|
||||||
|
// consume the outputs of the gc compiler both before and after a Go
|
||||||
|
// update such as from Go 1.7 to Go 1.8. Because this package lives in
|
||||||
|
// golang.org/x/tools, sites can update their version of this repo some
|
||||||
|
// time before the Go 1.8 release and rebuild and redeploy their
|
||||||
|
// developer tools, which will then be able to consume both Go 1.7 and
|
||||||
|
// Go 1.8 export data files, so they will work before and after the
|
||||||
|
// Go update. (See discussion at https://golang.org/issue/15651.)
|
||||||
|
package gcexportdata // import "golang.org/x/tools/go/gcexportdata"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/internal/gcimporter"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Find returns the name of an object (.o) or archive (.a) file
|
||||||
|
// containing type information for the specified import path,
|
||||||
|
// using the go command.
|
||||||
|
// If no file was found, an empty filename is returned.
|
||||||
|
//
|
||||||
|
// A relative srcDir is interpreted relative to the current working directory.
|
||||||
|
//
|
||||||
|
// Find also returns the package's resolved (canonical) import path,
|
||||||
|
// reflecting the effects of srcDir and vendoring on importPath.
|
||||||
|
//
|
||||||
|
// Deprecated: Use the higher-level API in golang.org/x/tools/go/packages,
|
||||||
|
// which is more efficient.
|
||||||
|
func Find(importPath, srcDir string) (filename, path string) {
|
||||||
|
cmd := exec.Command("go", "list", "-json", "-export", "--", importPath)
|
||||||
|
cmd.Dir = srcDir
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
var data struct {
|
||||||
|
ImportPath string
|
||||||
|
Export string
|
||||||
|
}
|
||||||
|
json.Unmarshal(out, &data)
|
||||||
|
return data.Export, data.ImportPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReader returns a reader for the export data section of an object
|
||||||
|
// (.o) or archive (.a) file read from r. The new reader may provide
|
||||||
|
// additional trailing data beyond the end of the export data.
|
||||||
|
func NewReader(r io.Reader) (io.Reader, error) {
|
||||||
|
buf := bufio.NewReader(r)
|
||||||
|
_, size, err := gcimporter.FindExportData(buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if size >= 0 {
|
||||||
|
// We were given an archive and found the __.PKGDEF in it.
|
||||||
|
// This tells us the size of the export data, and we don't
|
||||||
|
// need to return the entire file.
|
||||||
|
return &io.LimitedReader{
|
||||||
|
R: buf,
|
||||||
|
N: size,
|
||||||
|
}, nil
|
||||||
|
} else {
|
||||||
|
// We were given an object file. As such, we don't know how large
|
||||||
|
// the export data is and must return the entire file.
|
||||||
|
return buf, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read reads export data from in, decodes it, and returns type
|
||||||
|
// information for the package.
|
||||||
|
// The package name is specified by path.
|
||||||
|
// File position information is added to fset.
|
||||||
|
//
|
||||||
|
// Read may inspect and add to the imports map to ensure that references
|
||||||
|
// within the export data to other packages are consistent. The caller
|
||||||
|
// must ensure that imports[path] does not exist, or exists but is
|
||||||
|
// incomplete (see types.Package.Complete), and Read inserts the
|
||||||
|
// resulting package into this map entry.
|
||||||
|
//
|
||||||
|
// On return, the state of the reader is undefined.
|
||||||
|
func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package, path string) (*types.Package, error) {
|
||||||
|
data, err := ioutil.ReadAll(in)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("reading export data for %q: %v", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.HasPrefix(data, []byte("!<arch>")) {
|
||||||
|
return nil, fmt.Errorf("can't read export data for %q directly from an archive file (call gcexportdata.NewReader first to extract export data)", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The App Engine Go runtime v1.6 uses the old export data format.
|
||||||
|
// TODO(adonovan): delete once v1.7 has been around for a while.
|
||||||
|
if bytes.HasPrefix(data, []byte("package ")) {
|
||||||
|
return gcimporter.ImportData(imports, path, path, bytes.NewReader(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// The indexed export format starts with an 'i'; the older
|
||||||
|
// binary export format starts with a 'c', 'd', or 'v'
|
||||||
|
// (from "version"). Select appropriate importer.
|
||||||
|
if len(data) > 0 {
|
||||||
|
switch data[0] {
|
||||||
|
case 'i':
|
||||||
|
_, pkg, err := gcimporter.IImportData(fset, imports, data[1:], path)
|
||||||
|
return pkg, err
|
||||||
|
|
||||||
|
case 'v', 'c', 'd':
|
||||||
|
_, pkg, err := gcimporter.BImportData(fset, imports, data, path)
|
||||||
|
return pkg, err
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
_, pkg, err := gcimporter.UImportData(fset, imports, data[1:], path)
|
||||||
|
return pkg, err
|
||||||
|
|
||||||
|
default:
|
||||||
|
l := len(data)
|
||||||
|
if l > 10 {
|
||||||
|
l = 10
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unexpected export data with prefix %q for path %s", string(data[:l]), path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("empty export data for %s", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes encoded type information for the specified package to out.
|
||||||
|
// The FileSet provides file position information for named objects.
|
||||||
|
func Write(out io.Writer, fset *token.FileSet, pkg *types.Package) error {
|
||||||
|
if _, err := io.WriteString(out, "i"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return gcimporter.IExportData(out, fset, pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadBundle reads an export bundle from in, decodes it, and returns type
|
||||||
|
// information for the packages.
|
||||||
|
// File position information is added to fset.
|
||||||
|
//
|
||||||
|
// ReadBundle may inspect and add to the imports map to ensure that references
|
||||||
|
// within the export bundle to other packages are consistent.
|
||||||
|
//
|
||||||
|
// On return, the state of the reader is undefined.
|
||||||
|
//
|
||||||
|
// Experimental: This API is experimental and may change in the future.
|
||||||
|
func ReadBundle(in io.Reader, fset *token.FileSet, imports map[string]*types.Package) ([]*types.Package, error) {
|
||||||
|
data, err := ioutil.ReadAll(in)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("reading export bundle: %v", err)
|
||||||
|
}
|
||||||
|
return gcimporter.IImportBundle(fset, imports, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteBundle writes encoded type information for the specified packages to out.
|
||||||
|
// The FileSet provides file position information for named objects.
|
||||||
|
//
|
||||||
|
// Experimental: This API is experimental and may change in the future.
|
||||||
|
func WriteBundle(out io.Writer, fset *token.FileSet, pkgs []*types.Package) error {
|
||||||
|
return gcimporter.IExportBundle(out, fset, pkgs)
|
||||||
|
}
|
75
vendor/golang.org/x/tools/go/gcexportdata/importer.go
generated
vendored
Normal file
75
vendor/golang.org/x/tools/go/gcexportdata/importer.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gcexportdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewImporter returns a new instance of the types.Importer interface
|
||||||
|
// that reads type information from export data files written by gc.
|
||||||
|
// The Importer also satisfies types.ImporterFrom.
|
||||||
|
//
|
||||||
|
// Export data files are located using "go build" workspace conventions
|
||||||
|
// and the build.Default context.
|
||||||
|
//
|
||||||
|
// Use this importer instead of go/importer.For("gc", ...) to avoid the
|
||||||
|
// version-skew problems described in the documentation of this package,
|
||||||
|
// or to control the FileSet or access the imports map populated during
|
||||||
|
// package loading.
|
||||||
|
//
|
||||||
|
// Deprecated: Use the higher-level API in golang.org/x/tools/go/packages,
|
||||||
|
// which is more efficient.
|
||||||
|
func NewImporter(fset *token.FileSet, imports map[string]*types.Package) types.ImporterFrom {
|
||||||
|
return importer{fset, imports}
|
||||||
|
}
|
||||||
|
|
||||||
|
type importer struct {
|
||||||
|
fset *token.FileSet
|
||||||
|
imports map[string]*types.Package
|
||||||
|
}
|
||||||
|
|
||||||
|
func (imp importer) Import(importPath string) (*types.Package, error) {
|
||||||
|
return imp.ImportFrom(importPath, "", 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (imp importer) ImportFrom(importPath, srcDir string, mode types.ImportMode) (_ *types.Package, err error) {
|
||||||
|
filename, path := Find(importPath, srcDir)
|
||||||
|
if filename == "" {
|
||||||
|
if importPath == "unsafe" {
|
||||||
|
// Even for unsafe, call Find first in case
|
||||||
|
// the package was vendored.
|
||||||
|
return types.Unsafe, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("can't find import: %s", importPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pkg, ok := imp.imports[path]; ok && pkg.Complete() {
|
||||||
|
return pkg, nil // cache hit
|
||||||
|
}
|
||||||
|
|
||||||
|
// open file
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
f.Close()
|
||||||
|
if err != nil {
|
||||||
|
// add file name to error
|
||||||
|
err = fmt.Errorf("reading export data: %s: %v", filename, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
r, err := NewReader(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Read(r, imp.fset, imp.imports, path)
|
||||||
|
}
|
853
vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go
generated
vendored
Normal file
853
vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go
generated
vendored
Normal file
@ -0,0 +1,853 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
// Binary package export.
|
||||||
|
// This file was derived from $GOROOT/src/cmd/compile/internal/gc/bexport.go;
|
||||||
|
// see that file for specification of the format.
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/constant"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// If debugFormat is set, each integer and string value is preceded by a marker
|
||||||
|
// and position information in the encoding. This mechanism permits an importer
|
||||||
|
// to recognize immediately when it is out of sync. The importer recognizes this
|
||||||
|
// mode automatically (i.e., it can import export data produced with debugging
|
||||||
|
// support even if debugFormat is not set at the time of import). This mode will
|
||||||
|
// lead to massively larger export data (by a factor of 2 to 3) and should only
|
||||||
|
// be enabled during development and debugging.
|
||||||
|
//
|
||||||
|
// NOTE: This flag is the first flag to enable if importing dies because of
|
||||||
|
// (suspected) format errors, and whenever a change is made to the format.
|
||||||
|
const debugFormat = false // default: false
|
||||||
|
|
||||||
|
// Current export format version. Increase with each format change.
|
||||||
|
//
|
||||||
|
// Note: The latest binary (non-indexed) export format is at version 6.
|
||||||
|
// This exporter is still at level 4, but it doesn't matter since
|
||||||
|
// the binary importer can handle older versions just fine.
|
||||||
|
//
|
||||||
|
// 6: package height (CL 105038) -- NOT IMPLEMENTED HERE
|
||||||
|
// 5: improved position encoding efficiency (issue 20080, CL 41619) -- NOT IMPLEMENTED HERE
|
||||||
|
// 4: type name objects support type aliases, uses aliasTag
|
||||||
|
// 3: Go1.8 encoding (same as version 2, aliasTag defined but never used)
|
||||||
|
// 2: removed unused bool in ODCL export (compiler only)
|
||||||
|
// 1: header format change (more regular), export package for _ struct fields
|
||||||
|
// 0: Go1.7 encoding
|
||||||
|
const exportVersion = 4
|
||||||
|
|
||||||
|
// trackAllTypes enables cycle tracking for all types, not just named
|
||||||
|
// types. The existing compiler invariants assume that unnamed types
|
||||||
|
// that are not completely set up are not used, or else there are spurious
|
||||||
|
// errors.
|
||||||
|
// If disabled, only named types are tracked, possibly leading to slightly
|
||||||
|
// less efficient encoding in rare cases. It also prevents the export of
|
||||||
|
// some corner-case type declarations (but those are not handled correctly
|
||||||
|
// with with the textual export format either).
|
||||||
|
// TODO(gri) enable and remove once issues caused by it are fixed
|
||||||
|
const trackAllTypes = false
|
||||||
|
|
||||||
|
type exporter struct {
|
||||||
|
fset *token.FileSet
|
||||||
|
out bytes.Buffer
|
||||||
|
|
||||||
|
// object -> index maps, indexed in order of serialization
|
||||||
|
strIndex map[string]int
|
||||||
|
pkgIndex map[*types.Package]int
|
||||||
|
typIndex map[types.Type]int
|
||||||
|
|
||||||
|
// position encoding
|
||||||
|
posInfoFormat bool
|
||||||
|
prevFile string
|
||||||
|
prevLine int
|
||||||
|
|
||||||
|
// debugging support
|
||||||
|
written int // bytes written
|
||||||
|
indent int // for trace
|
||||||
|
}
|
||||||
|
|
||||||
|
// internalError represents an error generated inside this package.
|
||||||
|
type internalError string
|
||||||
|
|
||||||
|
func (e internalError) Error() string { return "gcimporter: " + string(e) }
|
||||||
|
|
||||||
|
func internalErrorf(format string, args ...interface{}) error {
|
||||||
|
return internalError(fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BExportData returns binary export data for pkg.
|
||||||
|
// If no file set is provided, position info will be missing.
|
||||||
|
func BExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) {
|
||||||
|
if !debug {
|
||||||
|
defer func() {
|
||||||
|
if e := recover(); e != nil {
|
||||||
|
if ierr, ok := e.(internalError); ok {
|
||||||
|
err = ierr
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Not an internal error; panic again.
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
p := exporter{
|
||||||
|
fset: fset,
|
||||||
|
strIndex: map[string]int{"": 0}, // empty string is mapped to 0
|
||||||
|
pkgIndex: make(map[*types.Package]int),
|
||||||
|
typIndex: make(map[types.Type]int),
|
||||||
|
posInfoFormat: true, // TODO(gri) might become a flag, eventually
|
||||||
|
}
|
||||||
|
|
||||||
|
// write version info
|
||||||
|
// The version string must start with "version %d" where %d is the version
|
||||||
|
// number. Additional debugging information may follow after a blank; that
|
||||||
|
// text is ignored by the importer.
|
||||||
|
p.rawStringln(fmt.Sprintf("version %d", exportVersion))
|
||||||
|
var debug string
|
||||||
|
if debugFormat {
|
||||||
|
debug = "debug"
|
||||||
|
}
|
||||||
|
p.rawStringln(debug) // cannot use p.bool since it's affected by debugFormat; also want to see this clearly
|
||||||
|
p.bool(trackAllTypes)
|
||||||
|
p.bool(p.posInfoFormat)
|
||||||
|
|
||||||
|
// --- generic export data ---
|
||||||
|
|
||||||
|
// populate type map with predeclared "known" types
|
||||||
|
for index, typ := range predeclared() {
|
||||||
|
p.typIndex[typ] = index
|
||||||
|
}
|
||||||
|
if len(p.typIndex) != len(predeclared()) {
|
||||||
|
return nil, internalError("duplicate entries in type map?")
|
||||||
|
}
|
||||||
|
|
||||||
|
// write package data
|
||||||
|
p.pkg(pkg, true)
|
||||||
|
if trace {
|
||||||
|
p.tracef("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// write objects
|
||||||
|
objcount := 0
|
||||||
|
scope := pkg.Scope()
|
||||||
|
for _, name := range scope.Names() {
|
||||||
|
if !ast.IsExported(name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if trace {
|
||||||
|
p.tracef("\n")
|
||||||
|
}
|
||||||
|
p.obj(scope.Lookup(name))
|
||||||
|
objcount++
|
||||||
|
}
|
||||||
|
|
||||||
|
// indicate end of list
|
||||||
|
if trace {
|
||||||
|
p.tracef("\n")
|
||||||
|
}
|
||||||
|
p.tag(endTag)
|
||||||
|
|
||||||
|
// for self-verification only (redundant)
|
||||||
|
p.int(objcount)
|
||||||
|
|
||||||
|
if trace {
|
||||||
|
p.tracef("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- end of export data ---
|
||||||
|
|
||||||
|
return p.out.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) pkg(pkg *types.Package, emptypath bool) {
|
||||||
|
if pkg == nil {
|
||||||
|
panic(internalError("unexpected nil pkg"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we saw the package before, write its index (>= 0)
|
||||||
|
if i, ok := p.pkgIndex[pkg]; ok {
|
||||||
|
p.index('P', i)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, remember the package, write the package tag (< 0) and package data
|
||||||
|
if trace {
|
||||||
|
p.tracef("P%d = { ", len(p.pkgIndex))
|
||||||
|
defer p.tracef("} ")
|
||||||
|
}
|
||||||
|
p.pkgIndex[pkg] = len(p.pkgIndex)
|
||||||
|
|
||||||
|
p.tag(packageTag)
|
||||||
|
p.string(pkg.Name())
|
||||||
|
if emptypath {
|
||||||
|
p.string("")
|
||||||
|
} else {
|
||||||
|
p.string(pkg.Path())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) obj(obj types.Object) {
|
||||||
|
switch obj := obj.(type) {
|
||||||
|
case *types.Const:
|
||||||
|
p.tag(constTag)
|
||||||
|
p.pos(obj)
|
||||||
|
p.qualifiedName(obj)
|
||||||
|
p.typ(obj.Type())
|
||||||
|
p.value(obj.Val())
|
||||||
|
|
||||||
|
case *types.TypeName:
|
||||||
|
if obj.IsAlias() {
|
||||||
|
p.tag(aliasTag)
|
||||||
|
p.pos(obj)
|
||||||
|
p.qualifiedName(obj)
|
||||||
|
} else {
|
||||||
|
p.tag(typeTag)
|
||||||
|
}
|
||||||
|
p.typ(obj.Type())
|
||||||
|
|
||||||
|
case *types.Var:
|
||||||
|
p.tag(varTag)
|
||||||
|
p.pos(obj)
|
||||||
|
p.qualifiedName(obj)
|
||||||
|
p.typ(obj.Type())
|
||||||
|
|
||||||
|
case *types.Func:
|
||||||
|
p.tag(funcTag)
|
||||||
|
p.pos(obj)
|
||||||
|
p.qualifiedName(obj)
|
||||||
|
sig := obj.Type().(*types.Signature)
|
||||||
|
p.paramList(sig.Params(), sig.Variadic())
|
||||||
|
p.paramList(sig.Results(), false)
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(internalErrorf("unexpected object %v (%T)", obj, obj))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) pos(obj types.Object) {
|
||||||
|
if !p.posInfoFormat {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file, line := p.fileLine(obj)
|
||||||
|
if file == p.prevFile {
|
||||||
|
// common case: write line delta
|
||||||
|
// delta == 0 means different file or no line change
|
||||||
|
delta := line - p.prevLine
|
||||||
|
p.int(delta)
|
||||||
|
if delta == 0 {
|
||||||
|
p.int(-1) // -1 means no file change
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// different file
|
||||||
|
p.int(0)
|
||||||
|
// Encode filename as length of common prefix with previous
|
||||||
|
// filename, followed by (possibly empty) suffix. Filenames
|
||||||
|
// frequently share path prefixes, so this can save a lot
|
||||||
|
// of space and make export data size less dependent on file
|
||||||
|
// path length. The suffix is unlikely to be empty because
|
||||||
|
// file names tend to end in ".go".
|
||||||
|
n := commonPrefixLen(p.prevFile, file)
|
||||||
|
p.int(n) // n >= 0
|
||||||
|
p.string(file[n:]) // write suffix only
|
||||||
|
p.prevFile = file
|
||||||
|
p.int(line)
|
||||||
|
}
|
||||||
|
p.prevLine = line
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) fileLine(obj types.Object) (file string, line int) {
|
||||||
|
if p.fset != nil {
|
||||||
|
pos := p.fset.Position(obj.Pos())
|
||||||
|
file = pos.Filename
|
||||||
|
line = pos.Line
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func commonPrefixLen(a, b string) int {
|
||||||
|
if len(a) > len(b) {
|
||||||
|
a, b = b, a
|
||||||
|
}
|
||||||
|
// len(a) <= len(b)
|
||||||
|
i := 0
|
||||||
|
for i < len(a) && a[i] == b[i] {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) qualifiedName(obj types.Object) {
|
||||||
|
p.string(obj.Name())
|
||||||
|
p.pkg(obj.Pkg(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) typ(t types.Type) {
|
||||||
|
if t == nil {
|
||||||
|
panic(internalError("nil type"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Possible optimization: Anonymous pointer types *T where
|
||||||
|
// T is a named type are common. We could canonicalize all
|
||||||
|
// such types *T to a single type PT = *T. This would lead
|
||||||
|
// to at most one *T entry in typIndex, and all future *T's
|
||||||
|
// would be encoded as the respective index directly. Would
|
||||||
|
// save 1 byte (pointerTag) per *T and reduce the typIndex
|
||||||
|
// size (at the cost of a canonicalization map). We can do
|
||||||
|
// this later, without encoding format change.
|
||||||
|
|
||||||
|
// if we saw the type before, write its index (>= 0)
|
||||||
|
if i, ok := p.typIndex[t]; ok {
|
||||||
|
p.index('T', i)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, remember the type, write the type tag (< 0) and type data
|
||||||
|
if trackAllTypes {
|
||||||
|
if trace {
|
||||||
|
p.tracef("T%d = {>\n", len(p.typIndex))
|
||||||
|
defer p.tracef("<\n} ")
|
||||||
|
}
|
||||||
|
p.typIndex[t] = len(p.typIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t := t.(type) {
|
||||||
|
case *types.Named:
|
||||||
|
if !trackAllTypes {
|
||||||
|
// if we don't track all types, track named types now
|
||||||
|
p.typIndex[t] = len(p.typIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.tag(namedTag)
|
||||||
|
p.pos(t.Obj())
|
||||||
|
p.qualifiedName(t.Obj())
|
||||||
|
p.typ(t.Underlying())
|
||||||
|
if !types.IsInterface(t) {
|
||||||
|
p.assocMethods(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Array:
|
||||||
|
p.tag(arrayTag)
|
||||||
|
p.int64(t.Len())
|
||||||
|
p.typ(t.Elem())
|
||||||
|
|
||||||
|
case *types.Slice:
|
||||||
|
p.tag(sliceTag)
|
||||||
|
p.typ(t.Elem())
|
||||||
|
|
||||||
|
case *dddSlice:
|
||||||
|
p.tag(dddTag)
|
||||||
|
p.typ(t.elem)
|
||||||
|
|
||||||
|
case *types.Struct:
|
||||||
|
p.tag(structTag)
|
||||||
|
p.fieldList(t)
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
p.tag(pointerTag)
|
||||||
|
p.typ(t.Elem())
|
||||||
|
|
||||||
|
case *types.Signature:
|
||||||
|
p.tag(signatureTag)
|
||||||
|
p.paramList(t.Params(), t.Variadic())
|
||||||
|
p.paramList(t.Results(), false)
|
||||||
|
|
||||||
|
case *types.Interface:
|
||||||
|
p.tag(interfaceTag)
|
||||||
|
p.iface(t)
|
||||||
|
|
||||||
|
case *types.Map:
|
||||||
|
p.tag(mapTag)
|
||||||
|
p.typ(t.Key())
|
||||||
|
p.typ(t.Elem())
|
||||||
|
|
||||||
|
case *types.Chan:
|
||||||
|
p.tag(chanTag)
|
||||||
|
p.int(int(3 - t.Dir())) // hack
|
||||||
|
p.typ(t.Elem())
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(internalErrorf("unexpected type %T: %s", t, t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) assocMethods(named *types.Named) {
|
||||||
|
// Sort methods (for determinism).
|
||||||
|
var methods []*types.Func
|
||||||
|
for i := 0; i < named.NumMethods(); i++ {
|
||||||
|
methods = append(methods, named.Method(i))
|
||||||
|
}
|
||||||
|
sort.Sort(methodsByName(methods))
|
||||||
|
|
||||||
|
p.int(len(methods))
|
||||||
|
|
||||||
|
if trace && methods != nil {
|
||||||
|
p.tracef("associated methods {>\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, m := range methods {
|
||||||
|
if trace && i > 0 {
|
||||||
|
p.tracef("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
p.pos(m)
|
||||||
|
name := m.Name()
|
||||||
|
p.string(name)
|
||||||
|
if !exported(name) {
|
||||||
|
p.pkg(m.Pkg(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
sig := m.Type().(*types.Signature)
|
||||||
|
p.paramList(types.NewTuple(sig.Recv()), false)
|
||||||
|
p.paramList(sig.Params(), sig.Variadic())
|
||||||
|
p.paramList(sig.Results(), false)
|
||||||
|
p.int(0) // dummy value for go:nointerface pragma - ignored by importer
|
||||||
|
}
|
||||||
|
|
||||||
|
if trace && methods != nil {
|
||||||
|
p.tracef("<\n} ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type methodsByName []*types.Func
|
||||||
|
|
||||||
|
func (x methodsByName) Len() int { return len(x) }
|
||||||
|
func (x methodsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||||
|
func (x methodsByName) Less(i, j int) bool { return x[i].Name() < x[j].Name() }
|
||||||
|
|
||||||
|
func (p *exporter) fieldList(t *types.Struct) {
|
||||||
|
if trace && t.NumFields() > 0 {
|
||||||
|
p.tracef("fields {>\n")
|
||||||
|
defer p.tracef("<\n} ")
|
||||||
|
}
|
||||||
|
|
||||||
|
p.int(t.NumFields())
|
||||||
|
for i := 0; i < t.NumFields(); i++ {
|
||||||
|
if trace && i > 0 {
|
||||||
|
p.tracef("\n")
|
||||||
|
}
|
||||||
|
p.field(t.Field(i))
|
||||||
|
p.string(t.Tag(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) field(f *types.Var) {
|
||||||
|
if !f.IsField() {
|
||||||
|
panic(internalError("field expected"))
|
||||||
|
}
|
||||||
|
|
||||||
|
p.pos(f)
|
||||||
|
p.fieldName(f)
|
||||||
|
p.typ(f.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) iface(t *types.Interface) {
|
||||||
|
// TODO(gri): enable importer to load embedded interfaces,
|
||||||
|
// then emit Embeddeds and ExplicitMethods separately here.
|
||||||
|
p.int(0)
|
||||||
|
|
||||||
|
n := t.NumMethods()
|
||||||
|
if trace && n > 0 {
|
||||||
|
p.tracef("methods {>\n")
|
||||||
|
defer p.tracef("<\n} ")
|
||||||
|
}
|
||||||
|
p.int(n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
if trace && i > 0 {
|
||||||
|
p.tracef("\n")
|
||||||
|
}
|
||||||
|
p.method(t.Method(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) method(m *types.Func) {
|
||||||
|
sig := m.Type().(*types.Signature)
|
||||||
|
if sig.Recv() == nil {
|
||||||
|
panic(internalError("method expected"))
|
||||||
|
}
|
||||||
|
|
||||||
|
p.pos(m)
|
||||||
|
p.string(m.Name())
|
||||||
|
if m.Name() != "_" && !ast.IsExported(m.Name()) {
|
||||||
|
p.pkg(m.Pkg(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// interface method; no need to encode receiver.
|
||||||
|
p.paramList(sig.Params(), sig.Variadic())
|
||||||
|
p.paramList(sig.Results(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) fieldName(f *types.Var) {
|
||||||
|
name := f.Name()
|
||||||
|
|
||||||
|
if f.Anonymous() {
|
||||||
|
// anonymous field - we distinguish between 3 cases:
|
||||||
|
// 1) field name matches base type name and is exported
|
||||||
|
// 2) field name matches base type name and is not exported
|
||||||
|
// 3) field name doesn't match base type name (alias name)
|
||||||
|
bname := basetypeName(f.Type())
|
||||||
|
if name == bname {
|
||||||
|
if ast.IsExported(name) {
|
||||||
|
name = "" // 1) we don't need to know the field name or package
|
||||||
|
} else {
|
||||||
|
name = "?" // 2) use unexported name "?" to force package export
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 3) indicate alias and export name as is
|
||||||
|
// (this requires an extra "@" but this is a rare case)
|
||||||
|
p.string("@")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.string(name)
|
||||||
|
if name != "" && !ast.IsExported(name) {
|
||||||
|
p.pkg(f.Pkg(), false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func basetypeName(typ types.Type) string {
|
||||||
|
switch typ := deref(typ).(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
return typ.Name()
|
||||||
|
case *types.Named:
|
||||||
|
return typ.Obj().Name()
|
||||||
|
default:
|
||||||
|
return "" // unnamed type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) paramList(params *types.Tuple, variadic bool) {
|
||||||
|
// use negative length to indicate unnamed parameters
|
||||||
|
// (look at the first parameter only since either all
|
||||||
|
// names are present or all are absent)
|
||||||
|
n := params.Len()
|
||||||
|
if n > 0 && params.At(0).Name() == "" {
|
||||||
|
n = -n
|
||||||
|
}
|
||||||
|
p.int(n)
|
||||||
|
for i := 0; i < params.Len(); i++ {
|
||||||
|
q := params.At(i)
|
||||||
|
t := q.Type()
|
||||||
|
if variadic && i == params.Len()-1 {
|
||||||
|
t = &dddSlice{t.(*types.Slice).Elem()}
|
||||||
|
}
|
||||||
|
p.typ(t)
|
||||||
|
if n > 0 {
|
||||||
|
name := q.Name()
|
||||||
|
p.string(name)
|
||||||
|
if name != "_" {
|
||||||
|
p.pkg(q.Pkg(), false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.string("") // no compiler-specific info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) value(x constant.Value) {
|
||||||
|
if trace {
|
||||||
|
p.tracef("= ")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch x.Kind() {
|
||||||
|
case constant.Bool:
|
||||||
|
tag := falseTag
|
||||||
|
if constant.BoolVal(x) {
|
||||||
|
tag = trueTag
|
||||||
|
}
|
||||||
|
p.tag(tag)
|
||||||
|
|
||||||
|
case constant.Int:
|
||||||
|
if v, exact := constant.Int64Val(x); exact {
|
||||||
|
// common case: x fits into an int64 - use compact encoding
|
||||||
|
p.tag(int64Tag)
|
||||||
|
p.int64(v)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// uncommon case: large x - use float encoding
|
||||||
|
// (powers of 2 will be encoded efficiently with exponent)
|
||||||
|
p.tag(floatTag)
|
||||||
|
p.float(constant.ToFloat(x))
|
||||||
|
|
||||||
|
case constant.Float:
|
||||||
|
p.tag(floatTag)
|
||||||
|
p.float(x)
|
||||||
|
|
||||||
|
case constant.Complex:
|
||||||
|
p.tag(complexTag)
|
||||||
|
p.float(constant.Real(x))
|
||||||
|
p.float(constant.Imag(x))
|
||||||
|
|
||||||
|
case constant.String:
|
||||||
|
p.tag(stringTag)
|
||||||
|
p.string(constant.StringVal(x))
|
||||||
|
|
||||||
|
case constant.Unknown:
|
||||||
|
// package contains type errors
|
||||||
|
p.tag(unknownTag)
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(internalErrorf("unexpected value %v (%T)", x, x))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) float(x constant.Value) {
|
||||||
|
if x.Kind() != constant.Float {
|
||||||
|
panic(internalErrorf("unexpected constant %v, want float", x))
|
||||||
|
}
|
||||||
|
// extract sign (there is no -0)
|
||||||
|
sign := constant.Sign(x)
|
||||||
|
if sign == 0 {
|
||||||
|
// x == 0
|
||||||
|
p.int(0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// x != 0
|
||||||
|
|
||||||
|
var f big.Float
|
||||||
|
if v, exact := constant.Float64Val(x); exact {
|
||||||
|
// float64
|
||||||
|
f.SetFloat64(v)
|
||||||
|
} else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int {
|
||||||
|
// TODO(gri): add big.Rat accessor to constant.Value.
|
||||||
|
r := valueToRat(num)
|
||||||
|
f.SetRat(r.Quo(r, valueToRat(denom)))
|
||||||
|
} else {
|
||||||
|
// Value too large to represent as a fraction => inaccessible.
|
||||||
|
// TODO(gri): add big.Float accessor to constant.Value.
|
||||||
|
f.SetFloat64(math.MaxFloat64) // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract exponent such that 0.5 <= m < 1.0
|
||||||
|
var m big.Float
|
||||||
|
exp := f.MantExp(&m)
|
||||||
|
|
||||||
|
// extract mantissa as *big.Int
|
||||||
|
// - set exponent large enough so mant satisfies mant.IsInt()
|
||||||
|
// - get *big.Int from mant
|
||||||
|
m.SetMantExp(&m, int(m.MinPrec()))
|
||||||
|
mant, acc := m.Int(nil)
|
||||||
|
if acc != big.Exact {
|
||||||
|
panic(internalError("internal error"))
|
||||||
|
}
|
||||||
|
|
||||||
|
p.int(sign)
|
||||||
|
p.int(exp)
|
||||||
|
p.string(string(mant.Bytes()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func valueToRat(x constant.Value) *big.Rat {
|
||||||
|
// Convert little-endian to big-endian.
|
||||||
|
// I can't believe this is necessary.
|
||||||
|
bytes := constant.Bytes(x)
|
||||||
|
for i := 0; i < len(bytes)/2; i++ {
|
||||||
|
bytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i]
|
||||||
|
}
|
||||||
|
return new(big.Rat).SetInt(new(big.Int).SetBytes(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) bool(b bool) bool {
|
||||||
|
if trace {
|
||||||
|
p.tracef("[")
|
||||||
|
defer p.tracef("= %v] ", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
x := 0
|
||||||
|
if b {
|
||||||
|
x = 1
|
||||||
|
}
|
||||||
|
p.int(x)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Low-level encoders
|
||||||
|
|
||||||
|
func (p *exporter) index(marker byte, index int) {
|
||||||
|
if index < 0 {
|
||||||
|
panic(internalError("invalid index < 0"))
|
||||||
|
}
|
||||||
|
if debugFormat {
|
||||||
|
p.marker('t')
|
||||||
|
}
|
||||||
|
if trace {
|
||||||
|
p.tracef("%c%d ", marker, index)
|
||||||
|
}
|
||||||
|
p.rawInt64(int64(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) tag(tag int) {
|
||||||
|
if tag >= 0 {
|
||||||
|
panic(internalError("invalid tag >= 0"))
|
||||||
|
}
|
||||||
|
if debugFormat {
|
||||||
|
p.marker('t')
|
||||||
|
}
|
||||||
|
if trace {
|
||||||
|
p.tracef("%s ", tagString[-tag])
|
||||||
|
}
|
||||||
|
p.rawInt64(int64(tag))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) int(x int) {
|
||||||
|
p.int64(int64(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) int64(x int64) {
|
||||||
|
if debugFormat {
|
||||||
|
p.marker('i')
|
||||||
|
}
|
||||||
|
if trace {
|
||||||
|
p.tracef("%d ", x)
|
||||||
|
}
|
||||||
|
p.rawInt64(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *exporter) string(s string) {
|
||||||
|
if debugFormat {
|
||||||
|
p.marker('s')
|
||||||
|
}
|
||||||
|
if trace {
|
||||||
|
p.tracef("%q ", s)
|
||||||
|
}
|
||||||
|
// if we saw the string before, write its index (>= 0)
|
||||||
|
// (the empty string is mapped to 0)
|
||||||
|
if i, ok := p.strIndex[s]; ok {
|
||||||
|
p.rawInt64(int64(i))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// otherwise, remember string and write its negative length and bytes
|
||||||
|
p.strIndex[s] = len(p.strIndex)
|
||||||
|
p.rawInt64(-int64(len(s)))
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
p.rawByte(s[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// marker emits a marker byte and position information which makes
|
||||||
|
// it easy for a reader to detect if it is "out of sync". Used for
|
||||||
|
// debugFormat format only.
|
||||||
|
func (p *exporter) marker(m byte) {
|
||||||
|
p.rawByte(m)
|
||||||
|
// Enable this for help tracking down the location
|
||||||
|
// of an incorrect marker when running in debugFormat.
|
||||||
|
if false && trace {
|
||||||
|
p.tracef("#%d ", p.written)
|
||||||
|
}
|
||||||
|
p.rawInt64(int64(p.written))
|
||||||
|
}
|
||||||
|
|
||||||
|
// rawInt64 should only be used by low-level encoders.
|
||||||
|
func (p *exporter) rawInt64(x int64) {
|
||||||
|
var tmp [binary.MaxVarintLen64]byte
|
||||||
|
n := binary.PutVarint(tmp[:], x)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
p.rawByte(tmp[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rawStringln should only be used to emit the initial version string.
|
||||||
|
func (p *exporter) rawStringln(s string) {
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
p.rawByte(s[i])
|
||||||
|
}
|
||||||
|
p.rawByte('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
// rawByte is the bottleneck interface to write to p.out.
|
||||||
|
// rawByte escapes b as follows (any encoding does that
|
||||||
|
// hides '$'):
|
||||||
|
//
|
||||||
|
// '$' => '|' 'S'
|
||||||
|
// '|' => '|' '|'
|
||||||
|
//
|
||||||
|
// Necessary so other tools can find the end of the
|
||||||
|
// export data by searching for "$$".
|
||||||
|
// rawByte should only be used by low-level encoders.
|
||||||
|
func (p *exporter) rawByte(b byte) {
|
||||||
|
switch b {
|
||||||
|
case '$':
|
||||||
|
// write '$' as '|' 'S'
|
||||||
|
b = 'S'
|
||||||
|
fallthrough
|
||||||
|
case '|':
|
||||||
|
// write '|' as '|' '|'
|
||||||
|
p.out.WriteByte('|')
|
||||||
|
p.written++
|
||||||
|
}
|
||||||
|
p.out.WriteByte(b)
|
||||||
|
p.written++
|
||||||
|
}
|
||||||
|
|
||||||
|
// tracef is like fmt.Printf but it rewrites the format string
|
||||||
|
// to take care of indentation.
|
||||||
|
func (p *exporter) tracef(format string, args ...interface{}) {
|
||||||
|
if strings.ContainsAny(format, "<>\n") {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for i := 0; i < len(format); i++ {
|
||||||
|
// no need to deal with runes
|
||||||
|
ch := format[i]
|
||||||
|
switch ch {
|
||||||
|
case '>':
|
||||||
|
p.indent++
|
||||||
|
continue
|
||||||
|
case '<':
|
||||||
|
p.indent--
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
buf.WriteByte(ch)
|
||||||
|
if ch == '\n' {
|
||||||
|
for j := p.indent; j > 0; j-- {
|
||||||
|
buf.WriteString(". ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
format = buf.String()
|
||||||
|
}
|
||||||
|
fmt.Printf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugging support.
|
||||||
|
// (tagString is only used when tracing is enabled)
|
||||||
|
var tagString = [...]string{
|
||||||
|
// Packages
|
||||||
|
-packageTag: "package",
|
||||||
|
|
||||||
|
// Types
|
||||||
|
-namedTag: "named type",
|
||||||
|
-arrayTag: "array",
|
||||||
|
-sliceTag: "slice",
|
||||||
|
-dddTag: "ddd",
|
||||||
|
-structTag: "struct",
|
||||||
|
-pointerTag: "pointer",
|
||||||
|
-signatureTag: "signature",
|
||||||
|
-interfaceTag: "interface",
|
||||||
|
-mapTag: "map",
|
||||||
|
-chanTag: "chan",
|
||||||
|
|
||||||
|
// Values
|
||||||
|
-falseTag: "false",
|
||||||
|
-trueTag: "true",
|
||||||
|
-int64Tag: "int64",
|
||||||
|
-floatTag: "float",
|
||||||
|
-fractionTag: "fraction",
|
||||||
|
-complexTag: "complex",
|
||||||
|
-stringTag: "string",
|
||||||
|
-unknownTag: "unknown",
|
||||||
|
|
||||||
|
// Type aliases
|
||||||
|
-aliasTag: "alias",
|
||||||
|
}
|
1053
vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go
generated
vendored
Normal file
1053
vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
99
vendor/golang.org/x/tools/go/internal/gcimporter/exportdata.go
generated
vendored
Normal file
99
vendor/golang.org/x/tools/go/internal/gcimporter/exportdata.go
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This file is a copy of $GOROOT/src/go/internal/gcimporter/exportdata.go.
|
||||||
|
|
||||||
|
// This file implements FindExportData.
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func readGopackHeader(r *bufio.Reader) (name string, size int64, err error) {
|
||||||
|
// See $GOROOT/include/ar.h.
|
||||||
|
hdr := make([]byte, 16+12+6+6+8+10+2)
|
||||||
|
_, err = io.ReadFull(r, hdr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// leave for debugging
|
||||||
|
if false {
|
||||||
|
fmt.Printf("header: %s", hdr)
|
||||||
|
}
|
||||||
|
s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
|
||||||
|
length, err := strconv.Atoi(s)
|
||||||
|
size = int64(length)
|
||||||
|
if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
|
||||||
|
err = fmt.Errorf("invalid archive header")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
name = strings.TrimSpace(string(hdr[:16]))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindExportData positions the reader r at the beginning of the
|
||||||
|
// export data section of an underlying GC-created object/archive
|
||||||
|
// file by reading from it. The reader must be positioned at the
|
||||||
|
// start of the file before calling this function. The hdr result
|
||||||
|
// is the string before the export data, either "$$" or "$$B".
|
||||||
|
// The size result is the length of the export data in bytes, or -1 if not known.
|
||||||
|
func FindExportData(r *bufio.Reader) (hdr string, size int64, err error) {
|
||||||
|
// Read first line to make sure this is an object file.
|
||||||
|
line, err := r.ReadSlice('\n')
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("can't find export data (%v)", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(line) == "!<arch>\n" {
|
||||||
|
// Archive file. Scan to __.PKGDEF.
|
||||||
|
var name string
|
||||||
|
if name, size, err = readGopackHeader(r); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// First entry should be __.PKGDEF.
|
||||||
|
if name != "__.PKGDEF" {
|
||||||
|
err = fmt.Errorf("go archive is missing __.PKGDEF")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read first line of __.PKGDEF data, so that line
|
||||||
|
// is once again the first line of the input.
|
||||||
|
if line, err = r.ReadSlice('\n'); err != nil {
|
||||||
|
err = fmt.Errorf("can't find export data (%v)", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
size -= int64(len(line))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now at __.PKGDEF in archive or still at beginning of file.
|
||||||
|
// Either way, line should begin with "go object ".
|
||||||
|
if !strings.HasPrefix(string(line), "go object ") {
|
||||||
|
err = fmt.Errorf("not a Go object file")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip over object header to export data.
|
||||||
|
// Begins after first line starting with $$.
|
||||||
|
for line[0] != '$' {
|
||||||
|
if line, err = r.ReadSlice('\n'); err != nil {
|
||||||
|
err = fmt.Errorf("can't find export data (%v)", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
size -= int64(len(line))
|
||||||
|
}
|
||||||
|
hdr = string(line)
|
||||||
|
if size < 0 {
|
||||||
|
size = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
1125
vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go
generated
vendored
Normal file
1125
vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1010
vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go
generated
vendored
Normal file
1010
vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
878
vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go
generated
vendored
Normal file
878
vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go
generated
vendored
Normal file
@ -0,0 +1,878 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Indexed package import.
|
||||||
|
// See cmd/compile/internal/gc/iexport.go for the export data format.
|
||||||
|
|
||||||
|
// This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go.
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"go/constant"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/typeparams"
|
||||||
|
)
|
||||||
|
|
||||||
|
type intReader struct {
|
||||||
|
*bytes.Reader
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *intReader) int64() int64 {
|
||||||
|
i, err := binary.ReadVarint(r.Reader)
|
||||||
|
if err != nil {
|
||||||
|
errorf("import %q: read varint error: %v", r.path, err)
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *intReader) uint64() uint64 {
|
||||||
|
i, err := binary.ReadUvarint(r.Reader)
|
||||||
|
if err != nil {
|
||||||
|
errorf("import %q: read varint error: %v", r.path, err)
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep this in sync with constants in iexport.go.
|
||||||
|
const (
|
||||||
|
iexportVersionGo1_11 = 0
|
||||||
|
iexportVersionPosCol = 1
|
||||||
|
iexportVersionGo1_18 = 2
|
||||||
|
iexportVersionGenerics = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type ident struct {
|
||||||
|
pkg *types.Package
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
const predeclReserved = 32
|
||||||
|
|
||||||
|
type itag uint64
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Types
|
||||||
|
definedType itag = iota
|
||||||
|
pointerType
|
||||||
|
sliceType
|
||||||
|
arrayType
|
||||||
|
chanType
|
||||||
|
mapType
|
||||||
|
signatureType
|
||||||
|
structType
|
||||||
|
interfaceType
|
||||||
|
typeParamType
|
||||||
|
instanceType
|
||||||
|
unionType
|
||||||
|
)
|
||||||
|
|
||||||
|
// IImportData imports a package from the serialized package data
|
||||||
|
// and returns 0 and a reference to the package.
|
||||||
|
// If the export data version is not recognized or the format is otherwise
|
||||||
|
// compromised, an error is returned.
|
||||||
|
func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
|
||||||
|
pkgs, err := iimportCommon(fset, imports, data, false, path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
return 0, pkgs[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IImportBundle imports a set of packages from the serialized package bundle.
|
||||||
|
func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) {
|
||||||
|
return iimportCommon(fset, imports, data, true, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string) (pkgs []*types.Package, err error) {
|
||||||
|
const currentVersion = 1
|
||||||
|
version := int64(-1)
|
||||||
|
if !debug {
|
||||||
|
defer func() {
|
||||||
|
if e := recover(); e != nil {
|
||||||
|
if bundle {
|
||||||
|
err = fmt.Errorf("%v", e)
|
||||||
|
} else if version > currentVersion {
|
||||||
|
err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &intReader{bytes.NewReader(data), path}
|
||||||
|
|
||||||
|
if bundle {
|
||||||
|
bundleVersion := r.uint64()
|
||||||
|
switch bundleVersion {
|
||||||
|
case bundleVersion:
|
||||||
|
default:
|
||||||
|
errorf("unknown bundle format version %d", bundleVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version = int64(r.uint64())
|
||||||
|
switch version {
|
||||||
|
case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:
|
||||||
|
default:
|
||||||
|
if version > iexportVersionGo1_18 {
|
||||||
|
errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
|
||||||
|
} else {
|
||||||
|
errorf("unknown iexport format version %d", version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sLen := int64(r.uint64())
|
||||||
|
dLen := int64(r.uint64())
|
||||||
|
|
||||||
|
whence, _ := r.Seek(0, io.SeekCurrent)
|
||||||
|
stringData := data[whence : whence+sLen]
|
||||||
|
declData := data[whence+sLen : whence+sLen+dLen]
|
||||||
|
r.Seek(sLen+dLen, io.SeekCurrent)
|
||||||
|
|
||||||
|
p := iimporter{
|
||||||
|
version: int(version),
|
||||||
|
ipath: path,
|
||||||
|
|
||||||
|
stringData: stringData,
|
||||||
|
stringCache: make(map[uint64]string),
|
||||||
|
pkgCache: make(map[uint64]*types.Package),
|
||||||
|
|
||||||
|
declData: declData,
|
||||||
|
pkgIndex: make(map[*types.Package]map[string]uint64),
|
||||||
|
typCache: make(map[uint64]types.Type),
|
||||||
|
// Separate map for typeparams, keyed by their package and unique
|
||||||
|
// name.
|
||||||
|
tparamIndex: make(map[ident]types.Type),
|
||||||
|
|
||||||
|
fake: fakeFileSet{
|
||||||
|
fset: fset,
|
||||||
|
files: make(map[string]*fileInfo),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
defer p.fake.setLines() // set lines for files in fset
|
||||||
|
|
||||||
|
for i, pt := range predeclared() {
|
||||||
|
p.typCache[uint64(i)] = pt
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgList := make([]*types.Package, r.uint64())
|
||||||
|
for i := range pkgList {
|
||||||
|
pkgPathOff := r.uint64()
|
||||||
|
pkgPath := p.stringAt(pkgPathOff)
|
||||||
|
pkgName := p.stringAt(r.uint64())
|
||||||
|
_ = r.uint64() // package height; unused by go/types
|
||||||
|
|
||||||
|
if pkgPath == "" {
|
||||||
|
pkgPath = path
|
||||||
|
}
|
||||||
|
pkg := imports[pkgPath]
|
||||||
|
if pkg == nil {
|
||||||
|
pkg = types.NewPackage(pkgPath, pkgName)
|
||||||
|
imports[pkgPath] = pkg
|
||||||
|
} else if pkg.Name() != pkgName {
|
||||||
|
errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.pkgCache[pkgPathOff] = pkg
|
||||||
|
|
||||||
|
nameIndex := make(map[string]uint64)
|
||||||
|
for nSyms := r.uint64(); nSyms > 0; nSyms-- {
|
||||||
|
name := p.stringAt(r.uint64())
|
||||||
|
nameIndex[name] = r.uint64()
|
||||||
|
}
|
||||||
|
|
||||||
|
p.pkgIndex[pkg] = nameIndex
|
||||||
|
pkgList[i] = pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
if bundle {
|
||||||
|
pkgs = make([]*types.Package, r.uint64())
|
||||||
|
for i := range pkgs {
|
||||||
|
pkg := p.pkgAt(r.uint64())
|
||||||
|
imps := make([]*types.Package, r.uint64())
|
||||||
|
for j := range imps {
|
||||||
|
imps[j] = p.pkgAt(r.uint64())
|
||||||
|
}
|
||||||
|
pkg.SetImports(imps)
|
||||||
|
pkgs[i] = pkg
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(pkgList) == 0 {
|
||||||
|
errorf("no packages found for %s", path)
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
pkgs = pkgList[:1]
|
||||||
|
|
||||||
|
// record all referenced packages as imports
|
||||||
|
list := append(([]*types.Package)(nil), pkgList[1:]...)
|
||||||
|
sort.Sort(byPath(list))
|
||||||
|
pkgs[0].SetImports(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
if pkg.Complete() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
names := make([]string, 0, len(p.pkgIndex[pkg]))
|
||||||
|
for name := range p.pkgIndex[pkg] {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
for _, name := range names {
|
||||||
|
p.doDecl(pkg, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// package was imported completely and without errors
|
||||||
|
pkg.MarkComplete()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetConstraint can't be called if the constraint type is not yet complete.
|
||||||
|
// When type params are created in the 'P' case of (*importReader).obj(),
|
||||||
|
// the associated constraint type may not be complete due to recursion.
|
||||||
|
// Therefore, we defer calling SetConstraint there, and call it here instead
|
||||||
|
// after all types are complete.
|
||||||
|
for _, d := range p.later {
|
||||||
|
typeparams.SetTypeParamConstraint(d.t, d.constraint)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, typ := range p.interfaceList {
|
||||||
|
typ.Complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkgs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type setConstraintArgs struct {
|
||||||
|
t *typeparams.TypeParam
|
||||||
|
constraint types.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
type iimporter struct {
|
||||||
|
version int
|
||||||
|
ipath string
|
||||||
|
|
||||||
|
stringData []byte
|
||||||
|
stringCache map[uint64]string
|
||||||
|
pkgCache map[uint64]*types.Package
|
||||||
|
|
||||||
|
declData []byte
|
||||||
|
pkgIndex map[*types.Package]map[string]uint64
|
||||||
|
typCache map[uint64]types.Type
|
||||||
|
tparamIndex map[ident]types.Type
|
||||||
|
|
||||||
|
fake fakeFileSet
|
||||||
|
interfaceList []*types.Interface
|
||||||
|
|
||||||
|
// Arguments for calls to SetConstraint that are deferred due to recursive types
|
||||||
|
later []setConstraintArgs
|
||||||
|
|
||||||
|
indent int // for tracing support
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *iimporter) trace(format string, args ...interface{}) {
|
||||||
|
if !trace {
|
||||||
|
// Call sites should also be guarded, but having this check here allows
|
||||||
|
// easily enabling/disabling debug trace statements.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf(strings.Repeat("..", p.indent)+format+"\n", args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *iimporter) doDecl(pkg *types.Package, name string) {
|
||||||
|
if debug {
|
||||||
|
p.trace("import decl %s", name)
|
||||||
|
p.indent++
|
||||||
|
defer func() {
|
||||||
|
p.indent--
|
||||||
|
p.trace("=> %s", name)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
// See if we've already imported this declaration.
|
||||||
|
if obj := pkg.Scope().Lookup(name); obj != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
off, ok := p.pkgIndex[pkg][name]
|
||||||
|
if !ok {
|
||||||
|
errorf("%v.%v not in index", pkg, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &importReader{p: p, currPkg: pkg}
|
||||||
|
r.declReader.Reset(p.declData[off:])
|
||||||
|
|
||||||
|
r.obj(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *iimporter) stringAt(off uint64) string {
|
||||||
|
if s, ok := p.stringCache[off]; ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
slen, n := binary.Uvarint(p.stringData[off:])
|
||||||
|
if n <= 0 {
|
||||||
|
errorf("varint failed")
|
||||||
|
}
|
||||||
|
spos := off + uint64(n)
|
||||||
|
s := string(p.stringData[spos : spos+slen])
|
||||||
|
p.stringCache[off] = s
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *iimporter) pkgAt(off uint64) *types.Package {
|
||||||
|
if pkg, ok := p.pkgCache[off]; ok {
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
path := p.stringAt(off)
|
||||||
|
errorf("missing package %q in %q", path, p.ipath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
|
||||||
|
if t, ok := p.typCache[off]; ok && canReuse(base, t) {
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
if off < predeclReserved {
|
||||||
|
errorf("predeclared type missing from cache: %v", off)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &importReader{p: p}
|
||||||
|
r.declReader.Reset(p.declData[off-predeclReserved:])
|
||||||
|
t := r.doType(base)
|
||||||
|
|
||||||
|
if canReuse(base, t) {
|
||||||
|
p.typCache[off] = t
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// canReuse reports whether the type rhs on the RHS of the declaration for def
|
||||||
|
// may be re-used.
|
||||||
|
//
|
||||||
|
// Specifically, if def is non-nil and rhs is an interface type with methods, it
|
||||||
|
// may not be re-used because we have a convention of setting the receiver type
|
||||||
|
// for interface methods to def.
|
||||||
|
func canReuse(def *types.Named, rhs types.Type) bool {
|
||||||
|
if def == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
iface, _ := rhs.(*types.Interface)
|
||||||
|
if iface == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Don't use iface.Empty() here as iface may not be complete.
|
||||||
|
return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type importReader struct {
|
||||||
|
p *iimporter
|
||||||
|
declReader bytes.Reader
|
||||||
|
currPkg *types.Package
|
||||||
|
prevFile string
|
||||||
|
prevLine int64
|
||||||
|
prevColumn int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) obj(name string) {
|
||||||
|
tag := r.byte()
|
||||||
|
pos := r.pos()
|
||||||
|
|
||||||
|
switch tag {
|
||||||
|
case 'A':
|
||||||
|
typ := r.typ()
|
||||||
|
|
||||||
|
r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
typ, val := r.value()
|
||||||
|
|
||||||
|
r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
|
||||||
|
|
||||||
|
case 'F', 'G':
|
||||||
|
var tparams []*typeparams.TypeParam
|
||||||
|
if tag == 'G' {
|
||||||
|
tparams = r.tparamList()
|
||||||
|
}
|
||||||
|
sig := r.signature(nil, nil, tparams)
|
||||||
|
r.declare(types.NewFunc(pos, r.currPkg, name, sig))
|
||||||
|
|
||||||
|
case 'T', 'U':
|
||||||
|
// Types can be recursive. We need to setup a stub
|
||||||
|
// declaration before recursing.
|
||||||
|
obj := types.NewTypeName(pos, r.currPkg, name, nil)
|
||||||
|
named := types.NewNamed(obj, nil, nil)
|
||||||
|
// Declare obj before calling r.tparamList, so the new type name is recognized
|
||||||
|
// if used in the constraint of one of its own typeparams (see #48280).
|
||||||
|
r.declare(obj)
|
||||||
|
if tag == 'U' {
|
||||||
|
tparams := r.tparamList()
|
||||||
|
typeparams.SetForNamed(named, tparams)
|
||||||
|
}
|
||||||
|
|
||||||
|
underlying := r.p.typAt(r.uint64(), named).Underlying()
|
||||||
|
named.SetUnderlying(underlying)
|
||||||
|
|
||||||
|
if !isInterface(underlying) {
|
||||||
|
for n := r.uint64(); n > 0; n-- {
|
||||||
|
mpos := r.pos()
|
||||||
|
mname := r.ident()
|
||||||
|
recv := r.param()
|
||||||
|
|
||||||
|
// If the receiver has any targs, set those as the
|
||||||
|
// rparams of the method (since those are the
|
||||||
|
// typeparams being used in the method sig/body).
|
||||||
|
base := baseType(recv.Type())
|
||||||
|
assert(base != nil)
|
||||||
|
targs := typeparams.NamedTypeArgs(base)
|
||||||
|
var rparams []*typeparams.TypeParam
|
||||||
|
if targs.Len() > 0 {
|
||||||
|
rparams = make([]*typeparams.TypeParam, targs.Len())
|
||||||
|
for i := range rparams {
|
||||||
|
rparams[i] = targs.At(i).(*typeparams.TypeParam)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msig := r.signature(recv, rparams, nil)
|
||||||
|
|
||||||
|
named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'P':
|
||||||
|
// We need to "declare" a typeparam in order to have a name that
|
||||||
|
// can be referenced recursively (if needed) in the type param's
|
||||||
|
// bound.
|
||||||
|
if r.p.version < iexportVersionGenerics {
|
||||||
|
errorf("unexpected type param type")
|
||||||
|
}
|
||||||
|
name0 := tparamName(name)
|
||||||
|
tn := types.NewTypeName(pos, r.currPkg, name0, nil)
|
||||||
|
t := typeparams.NewTypeParam(tn, nil)
|
||||||
|
|
||||||
|
// To handle recursive references to the typeparam within its
|
||||||
|
// bound, save the partial type in tparamIndex before reading the bounds.
|
||||||
|
id := ident{r.currPkg, name}
|
||||||
|
r.p.tparamIndex[id] = t
|
||||||
|
var implicit bool
|
||||||
|
if r.p.version >= iexportVersionGo1_18 {
|
||||||
|
implicit = r.bool()
|
||||||
|
}
|
||||||
|
constraint := r.typ()
|
||||||
|
if implicit {
|
||||||
|
iface, _ := constraint.(*types.Interface)
|
||||||
|
if iface == nil {
|
||||||
|
errorf("non-interface constraint marked implicit")
|
||||||
|
}
|
||||||
|
typeparams.MarkImplicit(iface)
|
||||||
|
}
|
||||||
|
// The constraint type may not be complete, if we
|
||||||
|
// are in the middle of a type recursion involving type
|
||||||
|
// constraints. So, we defer SetConstraint until we have
|
||||||
|
// completely set up all types in ImportData.
|
||||||
|
r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
|
||||||
|
|
||||||
|
case 'V':
|
||||||
|
typ := r.typ()
|
||||||
|
|
||||||
|
r.declare(types.NewVar(pos, r.currPkg, name, typ))
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorf("unexpected tag: %v", tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) declare(obj types.Object) {
|
||||||
|
obj.Pkg().Scope().Insert(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) value() (typ types.Type, val constant.Value) {
|
||||||
|
typ = r.typ()
|
||||||
|
if r.p.version >= iexportVersionGo1_18 {
|
||||||
|
// TODO: add support for using the kind.
|
||||||
|
_ = constant.Kind(r.int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
|
||||||
|
case types.IsBoolean:
|
||||||
|
val = constant.MakeBool(r.bool())
|
||||||
|
|
||||||
|
case types.IsString:
|
||||||
|
val = constant.MakeString(r.string())
|
||||||
|
|
||||||
|
case types.IsInteger:
|
||||||
|
var x big.Int
|
||||||
|
r.mpint(&x, b)
|
||||||
|
val = constant.Make(&x)
|
||||||
|
|
||||||
|
case types.IsFloat:
|
||||||
|
val = r.mpfloat(b)
|
||||||
|
|
||||||
|
case types.IsComplex:
|
||||||
|
re := r.mpfloat(b)
|
||||||
|
im := r.mpfloat(b)
|
||||||
|
val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
|
||||||
|
|
||||||
|
default:
|
||||||
|
if b.Kind() == types.Invalid {
|
||||||
|
val = constant.MakeUnknown()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
errorf("unexpected type %v", typ) // panics
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func intSize(b *types.Basic) (signed bool, maxBytes uint) {
|
||||||
|
if (b.Info() & types.IsUntyped) != 0 {
|
||||||
|
return true, 64
|
||||||
|
}
|
||||||
|
|
||||||
|
switch b.Kind() {
|
||||||
|
case types.Float32, types.Complex64:
|
||||||
|
return true, 3
|
||||||
|
case types.Float64, types.Complex128:
|
||||||
|
return true, 7
|
||||||
|
}
|
||||||
|
|
||||||
|
signed = (b.Info() & types.IsUnsigned) == 0
|
||||||
|
switch b.Kind() {
|
||||||
|
case types.Int8, types.Uint8:
|
||||||
|
maxBytes = 1
|
||||||
|
case types.Int16, types.Uint16:
|
||||||
|
maxBytes = 2
|
||||||
|
case types.Int32, types.Uint32:
|
||||||
|
maxBytes = 4
|
||||||
|
default:
|
||||||
|
maxBytes = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) mpint(x *big.Int, typ *types.Basic) {
|
||||||
|
signed, maxBytes := intSize(typ)
|
||||||
|
|
||||||
|
maxSmall := 256 - maxBytes
|
||||||
|
if signed {
|
||||||
|
maxSmall = 256 - 2*maxBytes
|
||||||
|
}
|
||||||
|
if maxBytes == 1 {
|
||||||
|
maxSmall = 256
|
||||||
|
}
|
||||||
|
|
||||||
|
n, _ := r.declReader.ReadByte()
|
||||||
|
if uint(n) < maxSmall {
|
||||||
|
v := int64(n)
|
||||||
|
if signed {
|
||||||
|
v >>= 1
|
||||||
|
if n&1 != 0 {
|
||||||
|
v = ^v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x.SetInt64(v)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v := -n
|
||||||
|
if signed {
|
||||||
|
v = -(n &^ 1) >> 1
|
||||||
|
}
|
||||||
|
if v < 1 || uint(v) > maxBytes {
|
||||||
|
errorf("weird decoding: %v, %v => %v", n, signed, v)
|
||||||
|
}
|
||||||
|
b := make([]byte, v)
|
||||||
|
io.ReadFull(&r.declReader, b)
|
||||||
|
x.SetBytes(b)
|
||||||
|
if signed && n&1 != 0 {
|
||||||
|
x.Neg(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) mpfloat(typ *types.Basic) constant.Value {
|
||||||
|
var mant big.Int
|
||||||
|
r.mpint(&mant, typ)
|
||||||
|
var f big.Float
|
||||||
|
f.SetInt(&mant)
|
||||||
|
if f.Sign() != 0 {
|
||||||
|
f.SetMantExp(&f, int(r.int64()))
|
||||||
|
}
|
||||||
|
return constant.Make(&f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) ident() string {
|
||||||
|
return r.string()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) qualifiedIdent() (*types.Package, string) {
|
||||||
|
name := r.string()
|
||||||
|
pkg := r.pkg()
|
||||||
|
return pkg, name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) pos() token.Pos {
|
||||||
|
if r.p.version >= iexportVersionPosCol {
|
||||||
|
r.posv1()
|
||||||
|
} else {
|
||||||
|
r.posv0()
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 {
|
||||||
|
return token.NoPos
|
||||||
|
}
|
||||||
|
return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) posv0() {
|
||||||
|
delta := r.int64()
|
||||||
|
if delta != deltaNewFile {
|
||||||
|
r.prevLine += delta
|
||||||
|
} else if l := r.int64(); l == -1 {
|
||||||
|
r.prevLine += deltaNewFile
|
||||||
|
} else {
|
||||||
|
r.prevFile = r.string()
|
||||||
|
r.prevLine = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) posv1() {
|
||||||
|
delta := r.int64()
|
||||||
|
r.prevColumn += delta >> 1
|
||||||
|
if delta&1 != 0 {
|
||||||
|
delta = r.int64()
|
||||||
|
r.prevLine += delta >> 1
|
||||||
|
if delta&1 != 0 {
|
||||||
|
r.prevFile = r.string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) typ() types.Type {
|
||||||
|
return r.p.typAt(r.uint64(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isInterface(t types.Type) bool {
|
||||||
|
_, ok := t.(*types.Interface)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
|
||||||
|
func (r *importReader) string() string { return r.p.stringAt(r.uint64()) }
|
||||||
|
|
||||||
|
func (r *importReader) doType(base *types.Named) (res types.Type) {
|
||||||
|
k := r.kind()
|
||||||
|
if debug {
|
||||||
|
r.p.trace("importing type %d (base: %s)", k, base)
|
||||||
|
r.p.indent++
|
||||||
|
defer func() {
|
||||||
|
r.p.indent--
|
||||||
|
r.p.trace("=> %s", res)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
switch k {
|
||||||
|
default:
|
||||||
|
errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case definedType:
|
||||||
|
pkg, name := r.qualifiedIdent()
|
||||||
|
r.p.doDecl(pkg, name)
|
||||||
|
return pkg.Scope().Lookup(name).(*types.TypeName).Type()
|
||||||
|
case pointerType:
|
||||||
|
return types.NewPointer(r.typ())
|
||||||
|
case sliceType:
|
||||||
|
return types.NewSlice(r.typ())
|
||||||
|
case arrayType:
|
||||||
|
n := r.uint64()
|
||||||
|
return types.NewArray(r.typ(), int64(n))
|
||||||
|
case chanType:
|
||||||
|
dir := chanDir(int(r.uint64()))
|
||||||
|
return types.NewChan(dir, r.typ())
|
||||||
|
case mapType:
|
||||||
|
return types.NewMap(r.typ(), r.typ())
|
||||||
|
case signatureType:
|
||||||
|
r.currPkg = r.pkg()
|
||||||
|
return r.signature(nil, nil, nil)
|
||||||
|
|
||||||
|
case structType:
|
||||||
|
r.currPkg = r.pkg()
|
||||||
|
|
||||||
|
fields := make([]*types.Var, r.uint64())
|
||||||
|
tags := make([]string, len(fields))
|
||||||
|
for i := range fields {
|
||||||
|
fpos := r.pos()
|
||||||
|
fname := r.ident()
|
||||||
|
ftyp := r.typ()
|
||||||
|
emb := r.bool()
|
||||||
|
tag := r.string()
|
||||||
|
|
||||||
|
fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
|
||||||
|
tags[i] = tag
|
||||||
|
}
|
||||||
|
return types.NewStruct(fields, tags)
|
||||||
|
|
||||||
|
case interfaceType:
|
||||||
|
r.currPkg = r.pkg()
|
||||||
|
|
||||||
|
embeddeds := make([]types.Type, r.uint64())
|
||||||
|
for i := range embeddeds {
|
||||||
|
_ = r.pos()
|
||||||
|
embeddeds[i] = r.typ()
|
||||||
|
}
|
||||||
|
|
||||||
|
methods := make([]*types.Func, r.uint64())
|
||||||
|
for i := range methods {
|
||||||
|
mpos := r.pos()
|
||||||
|
mname := r.ident()
|
||||||
|
|
||||||
|
// TODO(mdempsky): Matches bimport.go, but I
|
||||||
|
// don't agree with this.
|
||||||
|
var recv *types.Var
|
||||||
|
if base != nil {
|
||||||
|
recv = types.NewVar(token.NoPos, r.currPkg, "", base)
|
||||||
|
}
|
||||||
|
|
||||||
|
msig := r.signature(recv, nil, nil)
|
||||||
|
methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
|
||||||
|
}
|
||||||
|
|
||||||
|
typ := newInterface(methods, embeddeds)
|
||||||
|
r.p.interfaceList = append(r.p.interfaceList, typ)
|
||||||
|
return typ
|
||||||
|
|
||||||
|
case typeParamType:
|
||||||
|
if r.p.version < iexportVersionGenerics {
|
||||||
|
errorf("unexpected type param type")
|
||||||
|
}
|
||||||
|
pkg, name := r.qualifiedIdent()
|
||||||
|
id := ident{pkg, name}
|
||||||
|
if t, ok := r.p.tparamIndex[id]; ok {
|
||||||
|
// We're already in the process of importing this typeparam.
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
// Otherwise, import the definition of the typeparam now.
|
||||||
|
r.p.doDecl(pkg, name)
|
||||||
|
return r.p.tparamIndex[id]
|
||||||
|
|
||||||
|
case instanceType:
|
||||||
|
if r.p.version < iexportVersionGenerics {
|
||||||
|
errorf("unexpected instantiation type")
|
||||||
|
}
|
||||||
|
// pos does not matter for instances: they are positioned on the original
|
||||||
|
// type.
|
||||||
|
_ = r.pos()
|
||||||
|
len := r.uint64()
|
||||||
|
targs := make([]types.Type, len)
|
||||||
|
for i := range targs {
|
||||||
|
targs[i] = r.typ()
|
||||||
|
}
|
||||||
|
baseType := r.typ()
|
||||||
|
// The imported instantiated type doesn't include any methods, so
|
||||||
|
// we must always use the methods of the base (orig) type.
|
||||||
|
// TODO provide a non-nil *Environment
|
||||||
|
t, _ := typeparams.Instantiate(nil, baseType, targs, false)
|
||||||
|
return t
|
||||||
|
|
||||||
|
case unionType:
|
||||||
|
if r.p.version < iexportVersionGenerics {
|
||||||
|
errorf("unexpected instantiation type")
|
||||||
|
}
|
||||||
|
terms := make([]*typeparams.Term, r.uint64())
|
||||||
|
for i := range terms {
|
||||||
|
terms[i] = typeparams.NewTerm(r.bool(), r.typ())
|
||||||
|
}
|
||||||
|
return typeparams.NewUnion(terms)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) kind() itag {
|
||||||
|
return itag(r.uint64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) signature(recv *types.Var, rparams []*typeparams.TypeParam, tparams []*typeparams.TypeParam) *types.Signature {
|
||||||
|
params := r.paramList()
|
||||||
|
results := r.paramList()
|
||||||
|
variadic := params.Len() > 0 && r.bool()
|
||||||
|
return typeparams.NewSignatureType(recv, rparams, tparams, params, results, variadic)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) tparamList() []*typeparams.TypeParam {
|
||||||
|
n := r.uint64()
|
||||||
|
if n == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
xs := make([]*typeparams.TypeParam, n)
|
||||||
|
for i := range xs {
|
||||||
|
// Note: the standard library importer is tolerant of nil types here,
|
||||||
|
// though would panic in SetTypeParams.
|
||||||
|
xs[i] = r.typ().(*typeparams.TypeParam)
|
||||||
|
}
|
||||||
|
return xs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) paramList() *types.Tuple {
|
||||||
|
xs := make([]*types.Var, r.uint64())
|
||||||
|
for i := range xs {
|
||||||
|
xs[i] = r.param()
|
||||||
|
}
|
||||||
|
return types.NewTuple(xs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) param() *types.Var {
|
||||||
|
pos := r.pos()
|
||||||
|
name := r.ident()
|
||||||
|
typ := r.typ()
|
||||||
|
return types.NewParam(pos, r.currPkg, name, typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) bool() bool {
|
||||||
|
return r.uint64() != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) int64() int64 {
|
||||||
|
n, err := binary.ReadVarint(&r.declReader)
|
||||||
|
if err != nil {
|
||||||
|
errorf("readVarint: %v", err)
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) uint64() uint64 {
|
||||||
|
n, err := binary.ReadUvarint(&r.declReader)
|
||||||
|
if err != nil {
|
||||||
|
errorf("readUvarint: %v", err)
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *importReader) byte() byte {
|
||||||
|
x, err := r.declReader.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
errorf("declReader.ReadByte: %v", err)
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func baseType(typ types.Type) *types.Named {
|
||||||
|
// pointer receivers are never types.Named types
|
||||||
|
if p, _ := typ.(*types.Pointer); p != nil {
|
||||||
|
typ = p.Elem()
|
||||||
|
}
|
||||||
|
// receiver base types are always (possibly generic) types.Named types
|
||||||
|
n, _ := typ.(*types.Named)
|
||||||
|
return n
|
||||||
|
}
|
22
vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go
generated
vendored
Normal file
22
vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !go1.11
|
||||||
|
// +build !go1.11
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface {
|
||||||
|
named := make([]*types.Named, len(embeddeds))
|
||||||
|
for i, e := range embeddeds {
|
||||||
|
var ok bool
|
||||||
|
named[i], ok = e.(*types.Named)
|
||||||
|
if !ok {
|
||||||
|
panic("embedding of non-defined interfaces in interfaces is not supported before Go 1.11")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return types.NewInterface(methods, named)
|
||||||
|
}
|
14
vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go
generated
vendored
Normal file
14
vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build go1.11
|
||||||
|
// +build go1.11
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface {
|
||||||
|
return types.NewInterfaceType(methods, embeddeds)
|
||||||
|
}
|
16
vendor/golang.org/x/tools/go/internal/gcimporter/support_go117.go
generated
vendored
Normal file
16
vendor/golang.org/x/tools/go/internal/gcimporter/support_go117.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
//go:build !go1.18
|
||||||
|
// +build !go1.18
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
const iexportVersion = iexportVersionGo1_11
|
||||||
|
|
||||||
|
func additionalPredeclared() []types.Type {
|
||||||
|
return nil
|
||||||
|
}
|
23
vendor/golang.org/x/tools/go/internal/gcimporter/support_go118.go
generated
vendored
Normal file
23
vendor/golang.org/x/tools/go/internal/gcimporter/support_go118.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
//go:build go1.18
|
||||||
|
// +build go1.18
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
const iexportVersion = iexportVersionGenerics
|
||||||
|
|
||||||
|
// additionalPredeclared returns additional predeclared types in go.1.18.
|
||||||
|
func additionalPredeclared() []types.Type {
|
||||||
|
return []types.Type{
|
||||||
|
// comparable
|
||||||
|
types.Universe.Lookup("comparable").Type(),
|
||||||
|
|
||||||
|
// any
|
||||||
|
types.Universe.Lookup("any").Type(),
|
||||||
|
}
|
||||||
|
}
|
10
vendor/golang.org/x/tools/go/internal/gcimporter/unified_no.go
generated
vendored
Normal file
10
vendor/golang.org/x/tools/go/internal/gcimporter/unified_no.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2022 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.
|
||||||
|
|
||||||
|
//go:build !(go1.18 && goexperiment.unified)
|
||||||
|
// +build !go1.18 !goexperiment.unified
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
const unifiedIR = false
|
10
vendor/golang.org/x/tools/go/internal/gcimporter/unified_yes.go
generated
vendored
Normal file
10
vendor/golang.org/x/tools/go/internal/gcimporter/unified_yes.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2022 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.
|
||||||
|
|
||||||
|
//go:build go1.18 && goexperiment.unified
|
||||||
|
// +build go1.18,goexperiment.unified
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
const unifiedIR = true
|
19
vendor/golang.org/x/tools/go/internal/gcimporter/ureader_no.go
generated
vendored
Normal file
19
vendor/golang.org/x/tools/go/internal/gcimporter/ureader_no.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2022 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.
|
||||||
|
|
||||||
|
//go:build !go1.18
|
||||||
|
// +build !go1.18
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
||||||
|
err = fmt.Errorf("go/tools compiled with a Go version earlier than 1.18 cannot read unified IR export data")
|
||||||
|
return
|
||||||
|
}
|
612
vendor/golang.org/x/tools/go/internal/gcimporter/ureader_yes.go
generated
vendored
Normal file
612
vendor/golang.org/x/tools/go/internal/gcimporter/ureader_yes.go
generated
vendored
Normal file
@ -0,0 +1,612 @@
|
|||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
// Derived from go/internal/gcimporter/ureader.go
|
||||||
|
|
||||||
|
//go:build go1.18
|
||||||
|
// +build go1.18
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/internal/pkgbits"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A pkgReader holds the shared state for reading a unified IR package
|
||||||
|
// description.
|
||||||
|
type pkgReader struct {
|
||||||
|
pkgbits.PkgDecoder
|
||||||
|
|
||||||
|
fake fakeFileSet
|
||||||
|
|
||||||
|
ctxt *types.Context
|
||||||
|
imports map[string]*types.Package // previously imported packages, indexed by path
|
||||||
|
|
||||||
|
// lazily initialized arrays corresponding to the unified IR
|
||||||
|
// PosBase, Pkg, and Type sections, respectively.
|
||||||
|
posBases []string // position bases (i.e., file names)
|
||||||
|
pkgs []*types.Package
|
||||||
|
typs []types.Type
|
||||||
|
|
||||||
|
// laterFns holds functions that need to be invoked at the end of
|
||||||
|
// import reading.
|
||||||
|
laterFns []func()
|
||||||
|
}
|
||||||
|
|
||||||
|
// later adds a function to be invoked at the end of import reading.
|
||||||
|
func (pr *pkgReader) later(fn func()) {
|
||||||
|
pr.laterFns = append(pr.laterFns, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// See cmd/compile/internal/noder.derivedInfo.
|
||||||
|
type derivedInfo struct {
|
||||||
|
idx pkgbits.Index
|
||||||
|
needed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// See cmd/compile/internal/noder.typeInfo.
|
||||||
|
type typeInfo struct {
|
||||||
|
idx pkgbits.Index
|
||||||
|
derived bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
||||||
|
s := string(data)
|
||||||
|
s = s[:strings.LastIndex(s, "\n$$\n")]
|
||||||
|
input := pkgbits.NewPkgDecoder(path, s)
|
||||||
|
pkg = readUnifiedPackage(fset, nil, imports, input)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// readUnifiedPackage reads a package description from the given
|
||||||
|
// unified IR export data decoder.
|
||||||
|
func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package {
|
||||||
|
pr := pkgReader{
|
||||||
|
PkgDecoder: input,
|
||||||
|
|
||||||
|
fake: fakeFileSet{
|
||||||
|
fset: fset,
|
||||||
|
files: make(map[string]*fileInfo),
|
||||||
|
},
|
||||||
|
|
||||||
|
ctxt: ctxt,
|
||||||
|
imports: imports,
|
||||||
|
|
||||||
|
posBases: make([]string, input.NumElems(pkgbits.RelocPosBase)),
|
||||||
|
pkgs: make([]*types.Package, input.NumElems(pkgbits.RelocPkg)),
|
||||||
|
typs: make([]types.Type, input.NumElems(pkgbits.RelocType)),
|
||||||
|
}
|
||||||
|
defer pr.fake.setLines()
|
||||||
|
|
||||||
|
r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
|
||||||
|
pkg := r.pkg()
|
||||||
|
r.Bool() // has init
|
||||||
|
|
||||||
|
for i, n := 0, r.Len(); i < n; i++ {
|
||||||
|
// As if r.obj(), but avoiding the Scope.Lookup call,
|
||||||
|
// to avoid eager loading of imports.
|
||||||
|
r.Sync(pkgbits.SyncObject)
|
||||||
|
assert(!r.Bool())
|
||||||
|
r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
||||||
|
assert(r.Len() == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Sync(pkgbits.SyncEOF)
|
||||||
|
|
||||||
|
for _, fn := range pr.laterFns {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg.MarkComplete()
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
// A reader holds the state for reading a single unified IR element
|
||||||
|
// within a package.
|
||||||
|
type reader struct {
|
||||||
|
pkgbits.Decoder
|
||||||
|
|
||||||
|
p *pkgReader
|
||||||
|
|
||||||
|
dict *readerDict
|
||||||
|
}
|
||||||
|
|
||||||
|
// A readerDict holds the state for type parameters that parameterize
|
||||||
|
// the current unified IR element.
|
||||||
|
type readerDict struct {
|
||||||
|
// bounds is a slice of typeInfos corresponding to the underlying
|
||||||
|
// bounds of the element's type parameters.
|
||||||
|
bounds []typeInfo
|
||||||
|
|
||||||
|
// tparams is a slice of the constructed TypeParams for the element.
|
||||||
|
tparams []*types.TypeParam
|
||||||
|
|
||||||
|
// devived is a slice of types derived from tparams, which may be
|
||||||
|
// instantiated while reading the current element.
|
||||||
|
derived []derivedInfo
|
||||||
|
derivedTypes []types.Type // lazily instantiated from derived
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
|
||||||
|
return &reader{
|
||||||
|
Decoder: pr.NewDecoder(k, idx, marker),
|
||||||
|
p: pr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @@@ Positions
|
||||||
|
|
||||||
|
func (r *reader) pos() token.Pos {
|
||||||
|
r.Sync(pkgbits.SyncPos)
|
||||||
|
if !r.Bool() {
|
||||||
|
return token.NoPos
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(mdempsky): Delta encoding.
|
||||||
|
posBase := r.posBase()
|
||||||
|
line := r.Uint()
|
||||||
|
col := r.Uint()
|
||||||
|
return r.p.fake.pos(posBase, int(line), int(col))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) posBase() string {
|
||||||
|
return r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string {
|
||||||
|
if b := pr.posBases[idx]; b != "" {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
r := pr.newReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)
|
||||||
|
|
||||||
|
// Within types2, position bases have a lot more details (e.g.,
|
||||||
|
// keeping track of where //line directives appeared exactly).
|
||||||
|
//
|
||||||
|
// For go/types, we just track the file name.
|
||||||
|
|
||||||
|
filename := r.String()
|
||||||
|
|
||||||
|
if r.Bool() { // file base
|
||||||
|
// Was: "b = token.NewTrimmedFileBase(filename, true)"
|
||||||
|
} else { // line base
|
||||||
|
pos := r.pos()
|
||||||
|
line := r.Uint()
|
||||||
|
col := r.Uint()
|
||||||
|
|
||||||
|
// Was: "b = token.NewLineBase(pos, filename, true, line, col)"
|
||||||
|
_, _, _ = pos, line, col
|
||||||
|
}
|
||||||
|
|
||||||
|
b := filename
|
||||||
|
pr.posBases[idx] = b
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// @@@ Packages
|
||||||
|
|
||||||
|
func (r *reader) pkg() *types.Package {
|
||||||
|
r.Sync(pkgbits.SyncPkg)
|
||||||
|
return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Package {
|
||||||
|
// TODO(mdempsky): Consider using some non-nil pointer to indicate
|
||||||
|
// the universe scope, so we don't need to keep re-reading it.
|
||||||
|
if pkg := pr.pkgs[idx]; pkg != nil {
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg()
|
||||||
|
pr.pkgs[idx] = pkg
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) doPkg() *types.Package {
|
||||||
|
path := r.String()
|
||||||
|
switch path {
|
||||||
|
case "":
|
||||||
|
path = r.p.PkgPath()
|
||||||
|
case "builtin":
|
||||||
|
return nil // universe
|
||||||
|
case "unsafe":
|
||||||
|
return types.Unsafe
|
||||||
|
}
|
||||||
|
|
||||||
|
if pkg := r.p.imports[path]; pkg != nil {
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
name := r.String()
|
||||||
|
|
||||||
|
pkg := types.NewPackage(path, name)
|
||||||
|
r.p.imports[path] = pkg
|
||||||
|
|
||||||
|
imports := make([]*types.Package, r.Len())
|
||||||
|
for i := range imports {
|
||||||
|
imports[i] = r.pkg()
|
||||||
|
}
|
||||||
|
pkg.SetImports(imports)
|
||||||
|
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
// @@@ Types
|
||||||
|
|
||||||
|
func (r *reader) typ() types.Type {
|
||||||
|
return r.p.typIdx(r.typInfo(), r.dict)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) typInfo() typeInfo {
|
||||||
|
r.Sync(pkgbits.SyncType)
|
||||||
|
if r.Bool() {
|
||||||
|
return typeInfo{idx: pkgbits.Index(r.Len()), derived: true}
|
||||||
|
}
|
||||||
|
return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type {
|
||||||
|
idx := info.idx
|
||||||
|
var where *types.Type
|
||||||
|
if info.derived {
|
||||||
|
where = &dict.derivedTypes[idx]
|
||||||
|
idx = dict.derived[idx].idx
|
||||||
|
} else {
|
||||||
|
where = &pr.typs[idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
if typ := *where; typ != nil {
|
||||||
|
return typ
|
||||||
|
}
|
||||||
|
|
||||||
|
r := pr.newReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
|
||||||
|
r.dict = dict
|
||||||
|
|
||||||
|
typ := r.doTyp()
|
||||||
|
assert(typ != nil)
|
||||||
|
|
||||||
|
// See comment in pkgReader.typIdx explaining how this happens.
|
||||||
|
if prev := *where; prev != nil {
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
|
||||||
|
*where = typ
|
||||||
|
return typ
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) doTyp() (res types.Type) {
|
||||||
|
switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag {
|
||||||
|
default:
|
||||||
|
errorf("unhandled type tag: %v", tag)
|
||||||
|
panic("unreachable")
|
||||||
|
|
||||||
|
case pkgbits.TypeBasic:
|
||||||
|
return types.Typ[r.Len()]
|
||||||
|
|
||||||
|
case pkgbits.TypeNamed:
|
||||||
|
obj, targs := r.obj()
|
||||||
|
name := obj.(*types.TypeName)
|
||||||
|
if len(targs) != 0 {
|
||||||
|
t, _ := types.Instantiate(r.p.ctxt, name.Type(), targs, false)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
return name.Type()
|
||||||
|
|
||||||
|
case pkgbits.TypeTypeParam:
|
||||||
|
return r.dict.tparams[r.Len()]
|
||||||
|
|
||||||
|
case pkgbits.TypeArray:
|
||||||
|
len := int64(r.Uint64())
|
||||||
|
return types.NewArray(r.typ(), len)
|
||||||
|
case pkgbits.TypeChan:
|
||||||
|
dir := types.ChanDir(r.Len())
|
||||||
|
return types.NewChan(dir, r.typ())
|
||||||
|
case pkgbits.TypeMap:
|
||||||
|
return types.NewMap(r.typ(), r.typ())
|
||||||
|
case pkgbits.TypePointer:
|
||||||
|
return types.NewPointer(r.typ())
|
||||||
|
case pkgbits.TypeSignature:
|
||||||
|
return r.signature(nil, nil, nil)
|
||||||
|
case pkgbits.TypeSlice:
|
||||||
|
return types.NewSlice(r.typ())
|
||||||
|
case pkgbits.TypeStruct:
|
||||||
|
return r.structType()
|
||||||
|
case pkgbits.TypeInterface:
|
||||||
|
return r.interfaceType()
|
||||||
|
case pkgbits.TypeUnion:
|
||||||
|
return r.unionType()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) structType() *types.Struct {
|
||||||
|
fields := make([]*types.Var, r.Len())
|
||||||
|
var tags []string
|
||||||
|
for i := range fields {
|
||||||
|
pos := r.pos()
|
||||||
|
pkg, name := r.selector()
|
||||||
|
ftyp := r.typ()
|
||||||
|
tag := r.String()
|
||||||
|
embedded := r.Bool()
|
||||||
|
|
||||||
|
fields[i] = types.NewField(pos, pkg, name, ftyp, embedded)
|
||||||
|
if tag != "" {
|
||||||
|
for len(tags) < i {
|
||||||
|
tags = append(tags, "")
|
||||||
|
}
|
||||||
|
tags = append(tags, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return types.NewStruct(fields, tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) unionType() *types.Union {
|
||||||
|
terms := make([]*types.Term, r.Len())
|
||||||
|
for i := range terms {
|
||||||
|
terms[i] = types.NewTerm(r.Bool(), r.typ())
|
||||||
|
}
|
||||||
|
return types.NewUnion(terms)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) interfaceType() *types.Interface {
|
||||||
|
methods := make([]*types.Func, r.Len())
|
||||||
|
embeddeds := make([]types.Type, r.Len())
|
||||||
|
implicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool()
|
||||||
|
|
||||||
|
for i := range methods {
|
||||||
|
pos := r.pos()
|
||||||
|
pkg, name := r.selector()
|
||||||
|
mtyp := r.signature(nil, nil, nil)
|
||||||
|
methods[i] = types.NewFunc(pos, pkg, name, mtyp)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range embeddeds {
|
||||||
|
embeddeds[i] = r.typ()
|
||||||
|
}
|
||||||
|
|
||||||
|
iface := types.NewInterfaceType(methods, embeddeds)
|
||||||
|
if implicit {
|
||||||
|
iface.MarkImplicit()
|
||||||
|
}
|
||||||
|
return iface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) signature(recv *types.Var, rtparams, tparams []*types.TypeParam) *types.Signature {
|
||||||
|
r.Sync(pkgbits.SyncSignature)
|
||||||
|
|
||||||
|
params := r.params()
|
||||||
|
results := r.params()
|
||||||
|
variadic := r.Bool()
|
||||||
|
|
||||||
|
return types.NewSignatureType(recv, rtparams, tparams, params, results, variadic)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) params() *types.Tuple {
|
||||||
|
r.Sync(pkgbits.SyncParams)
|
||||||
|
|
||||||
|
params := make([]*types.Var, r.Len())
|
||||||
|
for i := range params {
|
||||||
|
params[i] = r.param()
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.NewTuple(params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) param() *types.Var {
|
||||||
|
r.Sync(pkgbits.SyncParam)
|
||||||
|
|
||||||
|
pos := r.pos()
|
||||||
|
pkg, name := r.localIdent()
|
||||||
|
typ := r.typ()
|
||||||
|
|
||||||
|
return types.NewParam(pos, pkg, name, typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @@@ Objects
|
||||||
|
|
||||||
|
func (r *reader) obj() (types.Object, []types.Type) {
|
||||||
|
r.Sync(pkgbits.SyncObject)
|
||||||
|
|
||||||
|
assert(!r.Bool())
|
||||||
|
|
||||||
|
pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
||||||
|
obj := pkgScope(pkg).Lookup(name)
|
||||||
|
|
||||||
|
targs := make([]types.Type, r.Len())
|
||||||
|
for i := range targs {
|
||||||
|
targs[i] = r.typ()
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj, targs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
|
||||||
|
rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
|
||||||
|
|
||||||
|
objPkg, objName := rname.qualifiedIdent()
|
||||||
|
assert(objName != "")
|
||||||
|
|
||||||
|
tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
|
||||||
|
|
||||||
|
if tag == pkgbits.ObjStub {
|
||||||
|
assert(objPkg == nil || objPkg == types.Unsafe)
|
||||||
|
return objPkg, objName
|
||||||
|
}
|
||||||
|
|
||||||
|
if objPkg.Scope().Lookup(objName) == nil {
|
||||||
|
dict := pr.objDictIdx(idx)
|
||||||
|
|
||||||
|
r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1)
|
||||||
|
r.dict = dict
|
||||||
|
|
||||||
|
declare := func(obj types.Object) {
|
||||||
|
objPkg.Scope().Insert(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch tag {
|
||||||
|
default:
|
||||||
|
panic("weird")
|
||||||
|
|
||||||
|
case pkgbits.ObjAlias:
|
||||||
|
pos := r.pos()
|
||||||
|
typ := r.typ()
|
||||||
|
declare(types.NewTypeName(pos, objPkg, objName, typ))
|
||||||
|
|
||||||
|
case pkgbits.ObjConst:
|
||||||
|
pos := r.pos()
|
||||||
|
typ := r.typ()
|
||||||
|
val := r.Value()
|
||||||
|
declare(types.NewConst(pos, objPkg, objName, typ, val))
|
||||||
|
|
||||||
|
case pkgbits.ObjFunc:
|
||||||
|
pos := r.pos()
|
||||||
|
tparams := r.typeParamNames()
|
||||||
|
sig := r.signature(nil, nil, tparams)
|
||||||
|
declare(types.NewFunc(pos, objPkg, objName, sig))
|
||||||
|
|
||||||
|
case pkgbits.ObjType:
|
||||||
|
pos := r.pos()
|
||||||
|
|
||||||
|
obj := types.NewTypeName(pos, objPkg, objName, nil)
|
||||||
|
named := types.NewNamed(obj, nil, nil)
|
||||||
|
declare(obj)
|
||||||
|
|
||||||
|
named.SetTypeParams(r.typeParamNames())
|
||||||
|
|
||||||
|
// TODO(mdempsky): Rewrite receiver types to underlying is an
|
||||||
|
// Interface? The go/types importer does this (I think because
|
||||||
|
// unit tests expected that), but cmd/compile doesn't care
|
||||||
|
// about it, so maybe we can avoid worrying about that here.
|
||||||
|
rhs := r.typ()
|
||||||
|
r.p.later(func() {
|
||||||
|
underlying := rhs.Underlying()
|
||||||
|
named.SetUnderlying(underlying)
|
||||||
|
})
|
||||||
|
|
||||||
|
for i, n := 0, r.Len(); i < n; i++ {
|
||||||
|
named.AddMethod(r.method())
|
||||||
|
}
|
||||||
|
|
||||||
|
case pkgbits.ObjVar:
|
||||||
|
pos := r.pos()
|
||||||
|
typ := r.typ()
|
||||||
|
declare(types.NewVar(pos, objPkg, objName, typ))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return objPkg, objName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
|
||||||
|
r := pr.newReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
|
||||||
|
|
||||||
|
var dict readerDict
|
||||||
|
|
||||||
|
if implicits := r.Len(); implicits != 0 {
|
||||||
|
errorf("unexpected object with %v implicit type parameter(s)", implicits)
|
||||||
|
}
|
||||||
|
|
||||||
|
dict.bounds = make([]typeInfo, r.Len())
|
||||||
|
for i := range dict.bounds {
|
||||||
|
dict.bounds[i] = r.typInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
dict.derived = make([]derivedInfo, r.Len())
|
||||||
|
dict.derivedTypes = make([]types.Type, len(dict.derived))
|
||||||
|
for i := range dict.derived {
|
||||||
|
dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function references follow, but reader doesn't need those
|
||||||
|
|
||||||
|
return &dict
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) typeParamNames() []*types.TypeParam {
|
||||||
|
r.Sync(pkgbits.SyncTypeParamNames)
|
||||||
|
|
||||||
|
// Note: This code assumes it only processes objects without
|
||||||
|
// implement type parameters. This is currently fine, because
|
||||||
|
// reader is only used to read in exported declarations, which are
|
||||||
|
// always package scoped.
|
||||||
|
|
||||||
|
if len(r.dict.bounds) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Careful: Type parameter lists may have cycles. To allow for this,
|
||||||
|
// we construct the type parameter list in two passes: first we
|
||||||
|
// create all the TypeNames and TypeParams, then we construct and
|
||||||
|
// set the bound type.
|
||||||
|
|
||||||
|
r.dict.tparams = make([]*types.TypeParam, len(r.dict.bounds))
|
||||||
|
for i := range r.dict.bounds {
|
||||||
|
pos := r.pos()
|
||||||
|
pkg, name := r.localIdent()
|
||||||
|
|
||||||
|
tname := types.NewTypeName(pos, pkg, name, nil)
|
||||||
|
r.dict.tparams[i] = types.NewTypeParam(tname, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
typs := make([]types.Type, len(r.dict.bounds))
|
||||||
|
for i, bound := range r.dict.bounds {
|
||||||
|
typs[i] = r.p.typIdx(bound, r.dict)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(mdempsky): This is subtle, elaborate further.
|
||||||
|
//
|
||||||
|
// We have to save tparams outside of the closure, because
|
||||||
|
// typeParamNames() can be called multiple times with the same
|
||||||
|
// dictionary instance.
|
||||||
|
//
|
||||||
|
// Also, this needs to happen later to make sure SetUnderlying has
|
||||||
|
// been called.
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): Is it safe to have a single "later" slice or do
|
||||||
|
// we need to have multiple passes? See comments on CL 386002 and
|
||||||
|
// go.dev/issue/52104.
|
||||||
|
tparams := r.dict.tparams
|
||||||
|
r.p.later(func() {
|
||||||
|
for i, typ := range typs {
|
||||||
|
tparams[i].SetConstraint(typ)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return r.dict.tparams
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) method() *types.Func {
|
||||||
|
r.Sync(pkgbits.SyncMethod)
|
||||||
|
pos := r.pos()
|
||||||
|
pkg, name := r.selector()
|
||||||
|
|
||||||
|
rparams := r.typeParamNames()
|
||||||
|
sig := r.signature(r.param(), rparams, nil)
|
||||||
|
|
||||||
|
_ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go.
|
||||||
|
return types.NewFunc(pos, pkg, name, sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) qualifiedIdent() (*types.Package, string) { return r.ident(pkgbits.SyncSym) }
|
||||||
|
func (r *reader) localIdent() (*types.Package, string) { return r.ident(pkgbits.SyncLocalIdent) }
|
||||||
|
func (r *reader) selector() (*types.Package, string) { return r.ident(pkgbits.SyncSelector) }
|
||||||
|
|
||||||
|
func (r *reader) ident(marker pkgbits.SyncMarker) (*types.Package, string) {
|
||||||
|
r.Sync(marker)
|
||||||
|
return r.pkg(), r.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// pkgScope returns pkg.Scope().
|
||||||
|
// If pkg is nil, it returns types.Universe instead.
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): Remove after x/tools can depend on Go 1.19.
|
||||||
|
func pkgScope(pkg *types.Package) *types.Scope {
|
||||||
|
if pkg != nil {
|
||||||
|
return pkg.Scope()
|
||||||
|
}
|
||||||
|
return types.Universe
|
||||||
|
}
|
49
vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
generated
vendored
Normal file
49
vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package packagesdriver fetches type sizes for go/packages and go/analysis.
|
||||||
|
package packagesdriver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/gocommand"
|
||||||
|
)
|
||||||
|
|
||||||
|
var debug = false
|
||||||
|
|
||||||
|
func GetSizesGolist(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (types.Sizes, error) {
|
||||||
|
inv.Verb = "list"
|
||||||
|
inv.Args = []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"}
|
||||||
|
stdout, stderr, friendlyErr, rawErr := gocmdRunner.RunRaw(ctx, inv)
|
||||||
|
var goarch, compiler string
|
||||||
|
if rawErr != nil {
|
||||||
|
if rawErrMsg := rawErr.Error(); strings.Contains(rawErrMsg, "cannot find main module") || strings.Contains(rawErrMsg, "go.mod file not found") {
|
||||||
|
// User's running outside of a module. All bets are off. Get GOARCH and guess compiler is gc.
|
||||||
|
// TODO(matloob): Is this a problem in practice?
|
||||||
|
inv.Verb = "env"
|
||||||
|
inv.Args = []string{"GOARCH"}
|
||||||
|
envout, enverr := gocmdRunner.Run(ctx, inv)
|
||||||
|
if enverr != nil {
|
||||||
|
return nil, enverr
|
||||||
|
}
|
||||||
|
goarch = strings.TrimSpace(envout.String())
|
||||||
|
compiler = "gc"
|
||||||
|
} else {
|
||||||
|
return nil, friendlyErr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fields := strings.Fields(stdout.String())
|
||||||
|
if len(fields) < 2 {
|
||||||
|
return nil, fmt.Errorf("could not parse GOARCH and Go compiler in format \"<GOARCH> <compiler>\":\nstdout: <<%s>>\nstderr: <<%s>>",
|
||||||
|
stdout.String(), stderr.String())
|
||||||
|
}
|
||||||
|
goarch = fields[0]
|
||||||
|
compiler = fields[1]
|
||||||
|
}
|
||||||
|
return types.SizesFor(compiler, goarch), nil
|
||||||
|
}
|
77
vendor/golang.org/x/tools/go/internal/pkgbits/codes.go
generated
vendored
Normal file
77
vendor/golang.org/x/tools/go/internal/pkgbits/codes.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
// A Code is an enum value that can be encoded into bitstreams.
|
||||||
|
//
|
||||||
|
// Code types are preferable for enum types, because they allow
|
||||||
|
// Decoder to detect desyncs.
|
||||||
|
type Code interface {
|
||||||
|
// Marker returns the SyncMarker for the Code's dynamic type.
|
||||||
|
Marker() SyncMarker
|
||||||
|
|
||||||
|
// Value returns the Code's ordinal value.
|
||||||
|
Value() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// A CodeVal distinguishes among go/constant.Value encodings.
|
||||||
|
type CodeVal int
|
||||||
|
|
||||||
|
func (c CodeVal) Marker() SyncMarker { return SyncVal }
|
||||||
|
func (c CodeVal) Value() int { return int(c) }
|
||||||
|
|
||||||
|
// Note: These values are public and cannot be changed without
|
||||||
|
// updating the go/types importers.
|
||||||
|
|
||||||
|
const (
|
||||||
|
ValBool CodeVal = iota
|
||||||
|
ValString
|
||||||
|
ValInt64
|
||||||
|
ValBigInt
|
||||||
|
ValBigRat
|
||||||
|
ValBigFloat
|
||||||
|
)
|
||||||
|
|
||||||
|
// A CodeType distinguishes among go/types.Type encodings.
|
||||||
|
type CodeType int
|
||||||
|
|
||||||
|
func (c CodeType) Marker() SyncMarker { return SyncType }
|
||||||
|
func (c CodeType) Value() int { return int(c) }
|
||||||
|
|
||||||
|
// Note: These values are public and cannot be changed without
|
||||||
|
// updating the go/types importers.
|
||||||
|
|
||||||
|
const (
|
||||||
|
TypeBasic CodeType = iota
|
||||||
|
TypeNamed
|
||||||
|
TypePointer
|
||||||
|
TypeSlice
|
||||||
|
TypeArray
|
||||||
|
TypeChan
|
||||||
|
TypeMap
|
||||||
|
TypeSignature
|
||||||
|
TypeStruct
|
||||||
|
TypeInterface
|
||||||
|
TypeUnion
|
||||||
|
TypeTypeParam
|
||||||
|
)
|
||||||
|
|
||||||
|
// A CodeObj distinguishes among go/types.Object encodings.
|
||||||
|
type CodeObj int
|
||||||
|
|
||||||
|
func (c CodeObj) Marker() SyncMarker { return SyncCodeObj }
|
||||||
|
func (c CodeObj) Value() int { return int(c) }
|
||||||
|
|
||||||
|
// Note: These values are public and cannot be changed without
|
||||||
|
// updating the go/types importers.
|
||||||
|
|
||||||
|
const (
|
||||||
|
ObjAlias CodeObj = iota
|
||||||
|
ObjConst
|
||||||
|
ObjType
|
||||||
|
ObjFunc
|
||||||
|
ObjVar
|
||||||
|
ObjStub
|
||||||
|
)
|
433
vendor/golang.org/x/tools/go/internal/pkgbits/decoder.go
generated
vendored
Normal file
433
vendor/golang.org/x/tools/go/internal/pkgbits/decoder.go
generated
vendored
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"go/constant"
|
||||||
|
"go/token"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A PkgDecoder provides methods for decoding a package's Unified IR
|
||||||
|
// export data.
|
||||||
|
type PkgDecoder struct {
|
||||||
|
// version is the file format version.
|
||||||
|
version uint32
|
||||||
|
|
||||||
|
// sync indicates whether the file uses sync markers.
|
||||||
|
sync bool
|
||||||
|
|
||||||
|
// pkgPath is the package path for the package to be decoded.
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): Remove; unneeded since CL 391014.
|
||||||
|
pkgPath string
|
||||||
|
|
||||||
|
// elemData is the full data payload of the encoded package.
|
||||||
|
// Elements are densely and contiguously packed together.
|
||||||
|
//
|
||||||
|
// The last 8 bytes of elemData are the package fingerprint.
|
||||||
|
elemData string
|
||||||
|
|
||||||
|
// elemEnds stores the byte-offset end positions of element
|
||||||
|
// bitstreams within elemData.
|
||||||
|
//
|
||||||
|
// For example, element I's bitstream data starts at elemEnds[I-1]
|
||||||
|
// (or 0, if I==0) and ends at elemEnds[I].
|
||||||
|
//
|
||||||
|
// Note: elemEnds is indexed by absolute indices, not
|
||||||
|
// section-relative indices.
|
||||||
|
elemEnds []uint32
|
||||||
|
|
||||||
|
// elemEndsEnds stores the index-offset end positions of relocation
|
||||||
|
// sections within elemEnds.
|
||||||
|
//
|
||||||
|
// For example, section K's end positions start at elemEndsEnds[K-1]
|
||||||
|
// (or 0, if K==0) and end at elemEndsEnds[K].
|
||||||
|
elemEndsEnds [numRelocs]uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// PkgPath returns the package path for the package
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): Remove; unneeded since CL 391014.
|
||||||
|
func (pr *PkgDecoder) PkgPath() string { return pr.pkgPath }
|
||||||
|
|
||||||
|
// SyncMarkers reports whether pr uses sync markers.
|
||||||
|
func (pr *PkgDecoder) SyncMarkers() bool { return pr.sync }
|
||||||
|
|
||||||
|
// NewPkgDecoder returns a PkgDecoder initialized to read the Unified
|
||||||
|
// IR export data from input. pkgPath is the package path for the
|
||||||
|
// compilation unit that produced the export data.
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): Remove pkgPath parameter; unneeded since CL 391014.
|
||||||
|
func NewPkgDecoder(pkgPath, input string) PkgDecoder {
|
||||||
|
pr := PkgDecoder{
|
||||||
|
pkgPath: pkgPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(mdempsky): Implement direct indexing of input string to
|
||||||
|
// avoid copying the position information.
|
||||||
|
|
||||||
|
r := strings.NewReader(input)
|
||||||
|
|
||||||
|
assert(binary.Read(r, binary.LittleEndian, &pr.version) == nil)
|
||||||
|
|
||||||
|
switch pr.version {
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unsupported version: %v", pr.version))
|
||||||
|
case 0:
|
||||||
|
// no flags
|
||||||
|
case 1:
|
||||||
|
var flags uint32
|
||||||
|
assert(binary.Read(r, binary.LittleEndian, &flags) == nil)
|
||||||
|
pr.sync = flags&flagSyncMarkers != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(binary.Read(r, binary.LittleEndian, pr.elemEndsEnds[:]) == nil)
|
||||||
|
|
||||||
|
pr.elemEnds = make([]uint32, pr.elemEndsEnds[len(pr.elemEndsEnds)-1])
|
||||||
|
assert(binary.Read(r, binary.LittleEndian, pr.elemEnds[:]) == nil)
|
||||||
|
|
||||||
|
pos, err := r.Seek(0, os.SEEK_CUR)
|
||||||
|
assert(err == nil)
|
||||||
|
|
||||||
|
pr.elemData = input[pos:]
|
||||||
|
assert(len(pr.elemData)-8 == int(pr.elemEnds[len(pr.elemEnds)-1]))
|
||||||
|
|
||||||
|
return pr
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumElems returns the number of elements in section k.
|
||||||
|
func (pr *PkgDecoder) NumElems(k RelocKind) int {
|
||||||
|
count := int(pr.elemEndsEnds[k])
|
||||||
|
if k > 0 {
|
||||||
|
count -= int(pr.elemEndsEnds[k-1])
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
// TotalElems returns the total number of elements across all sections.
|
||||||
|
func (pr *PkgDecoder) TotalElems() int {
|
||||||
|
return len(pr.elemEnds)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fingerprint returns the package fingerprint.
|
||||||
|
func (pr *PkgDecoder) Fingerprint() [8]byte {
|
||||||
|
var fp [8]byte
|
||||||
|
copy(fp[:], pr.elemData[len(pr.elemData)-8:])
|
||||||
|
return fp
|
||||||
|
}
|
||||||
|
|
||||||
|
// AbsIdx returns the absolute index for the given (section, index)
|
||||||
|
// pair.
|
||||||
|
func (pr *PkgDecoder) AbsIdx(k RelocKind, idx Index) int {
|
||||||
|
absIdx := int(idx)
|
||||||
|
if k > 0 {
|
||||||
|
absIdx += int(pr.elemEndsEnds[k-1])
|
||||||
|
}
|
||||||
|
if absIdx >= int(pr.elemEndsEnds[k]) {
|
||||||
|
errorf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds)
|
||||||
|
}
|
||||||
|
return absIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataIdx returns the raw element bitstream for the given (section,
|
||||||
|
// index) pair.
|
||||||
|
func (pr *PkgDecoder) DataIdx(k RelocKind, idx Index) string {
|
||||||
|
absIdx := pr.AbsIdx(k, idx)
|
||||||
|
|
||||||
|
var start uint32
|
||||||
|
if absIdx > 0 {
|
||||||
|
start = pr.elemEnds[absIdx-1]
|
||||||
|
}
|
||||||
|
end := pr.elemEnds[absIdx]
|
||||||
|
|
||||||
|
return pr.elemData[start:end]
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringIdx returns the string value for the given string index.
|
||||||
|
func (pr *PkgDecoder) StringIdx(idx Index) string {
|
||||||
|
return pr.DataIdx(RelocString, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDecoder returns a Decoder for the given (section, index) pair,
|
||||||
|
// and decodes the given SyncMarker from the element bitstream.
|
||||||
|
func (pr *PkgDecoder) NewDecoder(k RelocKind, idx Index, marker SyncMarker) Decoder {
|
||||||
|
r := pr.NewDecoderRaw(k, idx)
|
||||||
|
r.Sync(marker)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDecoderRaw returns a Decoder for the given (section, index) pair.
|
||||||
|
//
|
||||||
|
// Most callers should use NewDecoder instead.
|
||||||
|
func (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx Index) Decoder {
|
||||||
|
r := Decoder{
|
||||||
|
common: pr,
|
||||||
|
k: k,
|
||||||
|
Idx: idx,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(mdempsky) r.data.Reset(...) after #44505 is resolved.
|
||||||
|
r.Data = *strings.NewReader(pr.DataIdx(k, idx))
|
||||||
|
|
||||||
|
r.Sync(SyncRelocs)
|
||||||
|
r.Relocs = make([]RelocEnt, r.Len())
|
||||||
|
for i := range r.Relocs {
|
||||||
|
r.Sync(SyncReloc)
|
||||||
|
r.Relocs[i] = RelocEnt{RelocKind(r.Len()), Index(r.Len())}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Decoder provides methods for decoding an individual element's
|
||||||
|
// bitstream data.
|
||||||
|
type Decoder struct {
|
||||||
|
common *PkgDecoder
|
||||||
|
|
||||||
|
Relocs []RelocEnt
|
||||||
|
Data strings.Reader
|
||||||
|
|
||||||
|
k RelocKind
|
||||||
|
Idx Index
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Decoder) checkErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
errorf("unexpected decoding error: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Decoder) rawUvarint() uint64 {
|
||||||
|
x, err := binary.ReadUvarint(&r.Data)
|
||||||
|
r.checkErr(err)
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Decoder) rawVarint() int64 {
|
||||||
|
ux := r.rawUvarint()
|
||||||
|
|
||||||
|
// Zig-zag decode.
|
||||||
|
x := int64(ux >> 1)
|
||||||
|
if ux&1 != 0 {
|
||||||
|
x = ^x
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Decoder) rawReloc(k RelocKind, idx int) Index {
|
||||||
|
e := r.Relocs[idx]
|
||||||
|
assert(e.Kind == k)
|
||||||
|
return e.Idx
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync decodes a sync marker from the element bitstream and asserts
|
||||||
|
// that it matches the expected marker.
|
||||||
|
//
|
||||||
|
// If r.common.sync is false, then Sync is a no-op.
|
||||||
|
func (r *Decoder) Sync(mWant SyncMarker) {
|
||||||
|
if !r.common.sync {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pos, _ := r.Data.Seek(0, os.SEEK_CUR) // TODO(mdempsky): io.SeekCurrent after #44505 is resolved
|
||||||
|
mHave := SyncMarker(r.rawUvarint())
|
||||||
|
writerPCs := make([]int, r.rawUvarint())
|
||||||
|
for i := range writerPCs {
|
||||||
|
writerPCs[i] = int(r.rawUvarint())
|
||||||
|
}
|
||||||
|
|
||||||
|
if mHave == mWant {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// There's some tension here between printing:
|
||||||
|
//
|
||||||
|
// (1) full file paths that tools can recognize (e.g., so emacs
|
||||||
|
// hyperlinks the "file:line" text for easy navigation), or
|
||||||
|
//
|
||||||
|
// (2) short file paths that are easier for humans to read (e.g., by
|
||||||
|
// omitting redundant or irrelevant details, so it's easier to
|
||||||
|
// focus on the useful bits that remain).
|
||||||
|
//
|
||||||
|
// The current formatting favors the former, as it seems more
|
||||||
|
// helpful in practice. But perhaps the formatting could be improved
|
||||||
|
// to better address both concerns. For example, use relative file
|
||||||
|
// paths if they would be shorter, or rewrite file paths to contain
|
||||||
|
// "$GOROOT" (like objabi.AbsFile does) if tools can be taught how
|
||||||
|
// to reliably expand that again.
|
||||||
|
|
||||||
|
fmt.Printf("export data desync: package %q, section %v, index %v, offset %v\n", r.common.pkgPath, r.k, r.Idx, pos)
|
||||||
|
|
||||||
|
fmt.Printf("\nfound %v, written at:\n", mHave)
|
||||||
|
if len(writerPCs) == 0 {
|
||||||
|
fmt.Printf("\t[stack trace unavailable; recompile package %q with -d=syncframes]\n", r.common.pkgPath)
|
||||||
|
}
|
||||||
|
for _, pc := range writerPCs {
|
||||||
|
fmt.Printf("\t%s\n", r.common.StringIdx(r.rawReloc(RelocString, pc)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\nexpected %v, reading at:\n", mWant)
|
||||||
|
var readerPCs [32]uintptr // TODO(mdempsky): Dynamically size?
|
||||||
|
n := runtime.Callers(2, readerPCs[:])
|
||||||
|
for _, pc := range fmtFrames(readerPCs[:n]...) {
|
||||||
|
fmt.Printf("\t%s\n", pc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We already printed a stack trace for the reader, so now we can
|
||||||
|
// simply exit. Printing a second one with panic or base.Fatalf
|
||||||
|
// would just be noise.
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool decodes and returns a bool value from the element bitstream.
|
||||||
|
func (r *Decoder) Bool() bool {
|
||||||
|
r.Sync(SyncBool)
|
||||||
|
x, err := r.Data.ReadByte()
|
||||||
|
r.checkErr(err)
|
||||||
|
assert(x < 2)
|
||||||
|
return x != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 decodes and returns an int64 value from the element bitstream.
|
||||||
|
func (r *Decoder) Int64() int64 {
|
||||||
|
r.Sync(SyncInt64)
|
||||||
|
return r.rawVarint()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 decodes and returns a uint64 value from the element bitstream.
|
||||||
|
func (r *Decoder) Uint64() uint64 {
|
||||||
|
r.Sync(SyncUint64)
|
||||||
|
return r.rawUvarint()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len decodes and returns a non-negative int value from the element bitstream.
|
||||||
|
func (r *Decoder) Len() int { x := r.Uint64(); v := int(x); assert(uint64(v) == x); return v }
|
||||||
|
|
||||||
|
// Int decodes and returns an int value from the element bitstream.
|
||||||
|
func (r *Decoder) Int() int { x := r.Int64(); v := int(x); assert(int64(v) == x); return v }
|
||||||
|
|
||||||
|
// Uint decodes and returns a uint value from the element bitstream.
|
||||||
|
func (r *Decoder) Uint() uint { x := r.Uint64(); v := uint(x); assert(uint64(v) == x); return v }
|
||||||
|
|
||||||
|
// Code decodes a Code value from the element bitstream and returns
|
||||||
|
// its ordinal value. It's the caller's responsibility to convert the
|
||||||
|
// result to an appropriate Code type.
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): Ideally this method would have signature "Code[T
|
||||||
|
// Code] T" instead, but we don't allow generic methods and the
|
||||||
|
// compiler can't depend on generics yet anyway.
|
||||||
|
func (r *Decoder) Code(mark SyncMarker) int {
|
||||||
|
r.Sync(mark)
|
||||||
|
return r.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reloc decodes a relocation of expected section k from the element
|
||||||
|
// bitstream and returns an index to the referenced element.
|
||||||
|
func (r *Decoder) Reloc(k RelocKind) Index {
|
||||||
|
r.Sync(SyncUseReloc)
|
||||||
|
return r.rawReloc(k, r.Len())
|
||||||
|
}
|
||||||
|
|
||||||
|
// String decodes and returns a string value from the element
|
||||||
|
// bitstream.
|
||||||
|
func (r *Decoder) String() string {
|
||||||
|
r.Sync(SyncString)
|
||||||
|
return r.common.StringIdx(r.Reloc(RelocString))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strings decodes and returns a variable-length slice of strings from
|
||||||
|
// the element bitstream.
|
||||||
|
func (r *Decoder) Strings() []string {
|
||||||
|
res := make([]string, r.Len())
|
||||||
|
for i := range res {
|
||||||
|
res[i] = r.String()
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value decodes and returns a constant.Value from the element
|
||||||
|
// bitstream.
|
||||||
|
func (r *Decoder) Value() constant.Value {
|
||||||
|
r.Sync(SyncValue)
|
||||||
|
isComplex := r.Bool()
|
||||||
|
val := r.scalar()
|
||||||
|
if isComplex {
|
||||||
|
val = constant.BinaryOp(val, token.ADD, constant.MakeImag(r.scalar()))
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Decoder) scalar() constant.Value {
|
||||||
|
switch tag := CodeVal(r.Code(SyncVal)); tag {
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unexpected scalar tag: %v", tag))
|
||||||
|
|
||||||
|
case ValBool:
|
||||||
|
return constant.MakeBool(r.Bool())
|
||||||
|
case ValString:
|
||||||
|
return constant.MakeString(r.String())
|
||||||
|
case ValInt64:
|
||||||
|
return constant.MakeInt64(r.Int64())
|
||||||
|
case ValBigInt:
|
||||||
|
return constant.Make(r.bigInt())
|
||||||
|
case ValBigRat:
|
||||||
|
num := r.bigInt()
|
||||||
|
denom := r.bigInt()
|
||||||
|
return constant.Make(new(big.Rat).SetFrac(num, denom))
|
||||||
|
case ValBigFloat:
|
||||||
|
return constant.Make(r.bigFloat())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Decoder) bigInt() *big.Int {
|
||||||
|
v := new(big.Int).SetBytes([]byte(r.String()))
|
||||||
|
if r.Bool() {
|
||||||
|
v.Neg(v)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Decoder) bigFloat() *big.Float {
|
||||||
|
v := new(big.Float).SetPrec(512)
|
||||||
|
assert(v.UnmarshalText([]byte(r.String())) == nil)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// @@@ Helpers
|
||||||
|
|
||||||
|
// TODO(mdempsky): These should probably be removed. I think they're a
|
||||||
|
// smell that the export data format is not yet quite right.
|
||||||
|
|
||||||
|
// PeekPkgPath returns the package path for the specified package
|
||||||
|
// index.
|
||||||
|
func (pr *PkgDecoder) PeekPkgPath(idx Index) string {
|
||||||
|
r := pr.NewDecoder(RelocPkg, idx, SyncPkgDef)
|
||||||
|
path := r.String()
|
||||||
|
if path == "" {
|
||||||
|
path = pr.pkgPath
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeekObj returns the package path, object name, and CodeObj for the
|
||||||
|
// specified object index.
|
||||||
|
func (pr *PkgDecoder) PeekObj(idx Index) (string, string, CodeObj) {
|
||||||
|
r := pr.NewDecoder(RelocName, idx, SyncObject1)
|
||||||
|
r.Sync(SyncSym)
|
||||||
|
r.Sync(SyncPkg)
|
||||||
|
path := pr.PeekPkgPath(r.Reloc(RelocPkg))
|
||||||
|
name := r.String()
|
||||||
|
assert(name != "")
|
||||||
|
|
||||||
|
tag := CodeObj(r.Code(SyncCodeObj))
|
||||||
|
|
||||||
|
return path, name, tag
|
||||||
|
}
|
32
vendor/golang.org/x/tools/go/internal/pkgbits/doc.go
generated
vendored
Normal file
32
vendor/golang.org/x/tools/go/internal/pkgbits/doc.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package pkgbits implements low-level coding abstractions for
|
||||||
|
// Unified IR's export data format.
|
||||||
|
//
|
||||||
|
// At a low-level, a package is a collection of bitstream elements.
|
||||||
|
// Each element has a "kind" and a dense, non-negative index.
|
||||||
|
// Elements can be randomly accessed given their kind and index.
|
||||||
|
//
|
||||||
|
// Individual elements are sequences of variable-length values (e.g.,
|
||||||
|
// integers, booleans, strings, go/constant values, cross-references
|
||||||
|
// to other elements). Package pkgbits provides APIs for encoding and
|
||||||
|
// decoding these low-level values, but the details of mapping
|
||||||
|
// higher-level Go constructs into elements is left to higher-level
|
||||||
|
// abstractions.
|
||||||
|
//
|
||||||
|
// Elements may cross-reference each other with "relocations." For
|
||||||
|
// example, an element representing a pointer type has a relocation
|
||||||
|
// referring to the element type.
|
||||||
|
//
|
||||||
|
// Go constructs may be composed as a constellation of multiple
|
||||||
|
// elements. For example, a declared function may have one element to
|
||||||
|
// describe the object (e.g., its name, type, position), and a
|
||||||
|
// separate element to describe its function body. This allows readers
|
||||||
|
// some flexibility in efficiently seeking or re-reading data (e.g.,
|
||||||
|
// inlining requires re-reading the function body for each inlined
|
||||||
|
// call, without needing to re-read the object-level details).
|
||||||
|
//
|
||||||
|
// This is a copy of internal/pkgbits in the Go implementation.
|
||||||
|
package pkgbits
|
379
vendor/golang.org/x/tools/go/internal/pkgbits/encoder.go
generated
vendored
Normal file
379
vendor/golang.org/x/tools/go/internal/pkgbits/encoder.go
generated
vendored
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/binary"
|
||||||
|
"go/constant"
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// currentVersion is the current version number.
|
||||||
|
//
|
||||||
|
// - v0: initial prototype
|
||||||
|
//
|
||||||
|
// - v1: adds the flags uint32 word
|
||||||
|
const currentVersion uint32 = 1
|
||||||
|
|
||||||
|
// A PkgEncoder provides methods for encoding a package's Unified IR
|
||||||
|
// export data.
|
||||||
|
type PkgEncoder struct {
|
||||||
|
// elems holds the bitstream for previously encoded elements.
|
||||||
|
elems [numRelocs][]string
|
||||||
|
|
||||||
|
// stringsIdx maps previously encoded strings to their index within
|
||||||
|
// the RelocString section, to allow deduplication. That is,
|
||||||
|
// elems[RelocString][stringsIdx[s]] == s (if present).
|
||||||
|
stringsIdx map[string]Index
|
||||||
|
|
||||||
|
// syncFrames is the number of frames to write at each sync
|
||||||
|
// marker. A negative value means sync markers are omitted.
|
||||||
|
syncFrames int
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncMarkers reports whether pw uses sync markers.
|
||||||
|
func (pw *PkgEncoder) SyncMarkers() bool { return pw.syncFrames >= 0 }
|
||||||
|
|
||||||
|
// NewPkgEncoder returns an initialized PkgEncoder.
|
||||||
|
//
|
||||||
|
// syncFrames is the number of caller frames that should be serialized
|
||||||
|
// at Sync points. Serializing additional frames results in larger
|
||||||
|
// export data files, but can help diagnosing desync errors in
|
||||||
|
// higher-level Unified IR reader/writer code. If syncFrames is
|
||||||
|
// negative, then sync markers are omitted entirely.
|
||||||
|
func NewPkgEncoder(syncFrames int) PkgEncoder {
|
||||||
|
return PkgEncoder{
|
||||||
|
stringsIdx: make(map[string]Index),
|
||||||
|
syncFrames: syncFrames,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DumpTo writes the package's encoded data to out0 and returns the
|
||||||
|
// package fingerprint.
|
||||||
|
func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) {
|
||||||
|
h := md5.New()
|
||||||
|
out := io.MultiWriter(out0, h)
|
||||||
|
|
||||||
|
writeUint32 := func(x uint32) {
|
||||||
|
assert(binary.Write(out, binary.LittleEndian, x) == nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
writeUint32(currentVersion)
|
||||||
|
|
||||||
|
var flags uint32
|
||||||
|
if pw.SyncMarkers() {
|
||||||
|
flags |= flagSyncMarkers
|
||||||
|
}
|
||||||
|
writeUint32(flags)
|
||||||
|
|
||||||
|
// Write elemEndsEnds.
|
||||||
|
var sum uint32
|
||||||
|
for _, elems := range &pw.elems {
|
||||||
|
sum += uint32(len(elems))
|
||||||
|
writeUint32(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write elemEnds.
|
||||||
|
sum = 0
|
||||||
|
for _, elems := range &pw.elems {
|
||||||
|
for _, elem := range elems {
|
||||||
|
sum += uint32(len(elem))
|
||||||
|
writeUint32(sum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write elemData.
|
||||||
|
for _, elems := range &pw.elems {
|
||||||
|
for _, elem := range elems {
|
||||||
|
_, err := io.WriteString(out, elem)
|
||||||
|
assert(err == nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write fingerprint.
|
||||||
|
copy(fingerprint[:], h.Sum(nil))
|
||||||
|
_, err := out0.Write(fingerprint[:])
|
||||||
|
assert(err == nil)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringIdx adds a string value to the strings section, if not
|
||||||
|
// already present, and returns its index.
|
||||||
|
func (pw *PkgEncoder) StringIdx(s string) Index {
|
||||||
|
if idx, ok := pw.stringsIdx[s]; ok {
|
||||||
|
assert(pw.elems[RelocString][idx] == s)
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := Index(len(pw.elems[RelocString]))
|
||||||
|
pw.elems[RelocString] = append(pw.elems[RelocString], s)
|
||||||
|
pw.stringsIdx[s] = idx
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEncoder returns an Encoder for a new element within the given
|
||||||
|
// section, and encodes the given SyncMarker as the start of the
|
||||||
|
// element bitstream.
|
||||||
|
func (pw *PkgEncoder) NewEncoder(k RelocKind, marker SyncMarker) Encoder {
|
||||||
|
e := pw.NewEncoderRaw(k)
|
||||||
|
e.Sync(marker)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEncoderRaw returns an Encoder for a new element within the given
|
||||||
|
// section.
|
||||||
|
//
|
||||||
|
// Most callers should use NewEncoder instead.
|
||||||
|
func (pw *PkgEncoder) NewEncoderRaw(k RelocKind) Encoder {
|
||||||
|
idx := Index(len(pw.elems[k]))
|
||||||
|
pw.elems[k] = append(pw.elems[k], "") // placeholder
|
||||||
|
|
||||||
|
return Encoder{
|
||||||
|
p: pw,
|
||||||
|
k: k,
|
||||||
|
Idx: idx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Encoder provides methods for encoding an individual element's
|
||||||
|
// bitstream data.
|
||||||
|
type Encoder struct {
|
||||||
|
p *PkgEncoder
|
||||||
|
|
||||||
|
Relocs []RelocEnt
|
||||||
|
Data bytes.Buffer // accumulated element bitstream data
|
||||||
|
|
||||||
|
encodingRelocHeader bool
|
||||||
|
|
||||||
|
k RelocKind
|
||||||
|
Idx Index // index within relocation section
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush finalizes the element's bitstream and returns its Index.
|
||||||
|
func (w *Encoder) Flush() Index {
|
||||||
|
var sb bytes.Buffer // TODO(mdempsky): strings.Builder after #44505 is resolved
|
||||||
|
|
||||||
|
// Backup the data so we write the relocations at the front.
|
||||||
|
var tmp bytes.Buffer
|
||||||
|
io.Copy(&tmp, &w.Data)
|
||||||
|
|
||||||
|
// TODO(mdempsky): Consider writing these out separately so they're
|
||||||
|
// easier to strip, along with function bodies, so that we can prune
|
||||||
|
// down to just the data that's relevant to go/types.
|
||||||
|
if w.encodingRelocHeader {
|
||||||
|
panic("encodingRelocHeader already true; recursive flush?")
|
||||||
|
}
|
||||||
|
w.encodingRelocHeader = true
|
||||||
|
w.Sync(SyncRelocs)
|
||||||
|
w.Len(len(w.Relocs))
|
||||||
|
for _, rEnt := range w.Relocs {
|
||||||
|
w.Sync(SyncReloc)
|
||||||
|
w.Len(int(rEnt.Kind))
|
||||||
|
w.Len(int(rEnt.Idx))
|
||||||
|
}
|
||||||
|
|
||||||
|
io.Copy(&sb, &w.Data)
|
||||||
|
io.Copy(&sb, &tmp)
|
||||||
|
w.p.elems[w.k][w.Idx] = sb.String()
|
||||||
|
|
||||||
|
return w.Idx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Encoder) checkErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
errorf("unexpected encoding error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Encoder) rawUvarint(x uint64) {
|
||||||
|
var buf [binary.MaxVarintLen64]byte
|
||||||
|
n := binary.PutUvarint(buf[:], x)
|
||||||
|
_, err := w.Data.Write(buf[:n])
|
||||||
|
w.checkErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Encoder) rawVarint(x int64) {
|
||||||
|
// Zig-zag encode.
|
||||||
|
ux := uint64(x) << 1
|
||||||
|
if x < 0 {
|
||||||
|
ux = ^ux
|
||||||
|
}
|
||||||
|
|
||||||
|
w.rawUvarint(ux)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Encoder) rawReloc(r RelocKind, idx Index) int {
|
||||||
|
// TODO(mdempsky): Use map for lookup; this takes quadratic time.
|
||||||
|
for i, rEnt := range w.Relocs {
|
||||||
|
if rEnt.Kind == r && rEnt.Idx == idx {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i := len(w.Relocs)
|
||||||
|
w.Relocs = append(w.Relocs, RelocEnt{r, idx})
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Encoder) Sync(m SyncMarker) {
|
||||||
|
if !w.p.SyncMarkers() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writing out stack frame string references requires working
|
||||||
|
// relocations, but writing out the relocations themselves involves
|
||||||
|
// sync markers. To prevent infinite recursion, we simply trim the
|
||||||
|
// stack frame for sync markers within the relocation header.
|
||||||
|
var frames []string
|
||||||
|
if !w.encodingRelocHeader && w.p.syncFrames > 0 {
|
||||||
|
pcs := make([]uintptr, w.p.syncFrames)
|
||||||
|
n := runtime.Callers(2, pcs)
|
||||||
|
frames = fmtFrames(pcs[:n]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(mdempsky): Save space by writing out stack frames as a
|
||||||
|
// linked list so we can share common stack frames.
|
||||||
|
w.rawUvarint(uint64(m))
|
||||||
|
w.rawUvarint(uint64(len(frames)))
|
||||||
|
for _, frame := range frames {
|
||||||
|
w.rawUvarint(uint64(w.rawReloc(RelocString, w.p.StringIdx(frame))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool encodes and writes a bool value into the element bitstream,
|
||||||
|
// and then returns the bool value.
|
||||||
|
//
|
||||||
|
// For simple, 2-alternative encodings, the idiomatic way to call Bool
|
||||||
|
// is something like:
|
||||||
|
//
|
||||||
|
// if w.Bool(x != 0) {
|
||||||
|
// // alternative #1
|
||||||
|
// } else {
|
||||||
|
// // alternative #2
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// For multi-alternative encodings, use Code instead.
|
||||||
|
func (w *Encoder) Bool(b bool) bool {
|
||||||
|
w.Sync(SyncBool)
|
||||||
|
var x byte
|
||||||
|
if b {
|
||||||
|
x = 1
|
||||||
|
}
|
||||||
|
err := w.Data.WriteByte(x)
|
||||||
|
w.checkErr(err)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 encodes and writes an int64 value into the element bitstream.
|
||||||
|
func (w *Encoder) Int64(x int64) {
|
||||||
|
w.Sync(SyncInt64)
|
||||||
|
w.rawVarint(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 encodes and writes a uint64 value into the element bitstream.
|
||||||
|
func (w *Encoder) Uint64(x uint64) {
|
||||||
|
w.Sync(SyncUint64)
|
||||||
|
w.rawUvarint(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len encodes and writes a non-negative int value into the element bitstream.
|
||||||
|
func (w *Encoder) Len(x int) { assert(x >= 0); w.Uint64(uint64(x)) }
|
||||||
|
|
||||||
|
// Int encodes and writes an int value into the element bitstream.
|
||||||
|
func (w *Encoder) Int(x int) { w.Int64(int64(x)) }
|
||||||
|
|
||||||
|
// Len encodes and writes a uint value into the element bitstream.
|
||||||
|
func (w *Encoder) Uint(x uint) { w.Uint64(uint64(x)) }
|
||||||
|
|
||||||
|
// Reloc encodes and writes a relocation for the given (section,
|
||||||
|
// index) pair into the element bitstream.
|
||||||
|
//
|
||||||
|
// Note: Only the index is formally written into the element
|
||||||
|
// bitstream, so bitstream decoders must know from context which
|
||||||
|
// section an encoded relocation refers to.
|
||||||
|
func (w *Encoder) Reloc(r RelocKind, idx Index) {
|
||||||
|
w.Sync(SyncUseReloc)
|
||||||
|
w.Len(w.rawReloc(r, idx))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code encodes and writes a Code value into the element bitstream.
|
||||||
|
func (w *Encoder) Code(c Code) {
|
||||||
|
w.Sync(c.Marker())
|
||||||
|
w.Len(c.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// String encodes and writes a string value into the element
|
||||||
|
// bitstream.
|
||||||
|
//
|
||||||
|
// Internally, strings are deduplicated by adding them to the strings
|
||||||
|
// section (if not already present), and then writing a relocation
|
||||||
|
// into the element bitstream.
|
||||||
|
func (w *Encoder) String(s string) {
|
||||||
|
w.Sync(SyncString)
|
||||||
|
w.Reloc(RelocString, w.p.StringIdx(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strings encodes and writes a variable-length slice of strings into
|
||||||
|
// the element bitstream.
|
||||||
|
func (w *Encoder) Strings(ss []string) {
|
||||||
|
w.Len(len(ss))
|
||||||
|
for _, s := range ss {
|
||||||
|
w.String(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value encodes and writes a constant.Value into the element
|
||||||
|
// bitstream.
|
||||||
|
func (w *Encoder) Value(val constant.Value) {
|
||||||
|
w.Sync(SyncValue)
|
||||||
|
if w.Bool(val.Kind() == constant.Complex) {
|
||||||
|
w.scalar(constant.Real(val))
|
||||||
|
w.scalar(constant.Imag(val))
|
||||||
|
} else {
|
||||||
|
w.scalar(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Encoder) scalar(val constant.Value) {
|
||||||
|
switch v := constant.Val(val).(type) {
|
||||||
|
default:
|
||||||
|
errorf("unhandled %v (%v)", val, val.Kind())
|
||||||
|
case bool:
|
||||||
|
w.Code(ValBool)
|
||||||
|
w.Bool(v)
|
||||||
|
case string:
|
||||||
|
w.Code(ValString)
|
||||||
|
w.String(v)
|
||||||
|
case int64:
|
||||||
|
w.Code(ValInt64)
|
||||||
|
w.Int64(v)
|
||||||
|
case *big.Int:
|
||||||
|
w.Code(ValBigInt)
|
||||||
|
w.bigInt(v)
|
||||||
|
case *big.Rat:
|
||||||
|
w.Code(ValBigRat)
|
||||||
|
w.bigInt(v.Num())
|
||||||
|
w.bigInt(v.Denom())
|
||||||
|
case *big.Float:
|
||||||
|
w.Code(ValBigFloat)
|
||||||
|
w.bigFloat(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Encoder) bigInt(v *big.Int) {
|
||||||
|
b := v.Bytes()
|
||||||
|
w.String(string(b)) // TODO: More efficient encoding.
|
||||||
|
w.Bool(v.Sign() < 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Encoder) bigFloat(v *big.Float) {
|
||||||
|
b := v.Append(nil, 'p', -1)
|
||||||
|
w.String(string(b)) // TODO: More efficient encoding.
|
||||||
|
}
|
9
vendor/golang.org/x/tools/go/internal/pkgbits/flags.go
generated
vendored
Normal file
9
vendor/golang.org/x/tools/go/internal/pkgbits/flags.go
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
const (
|
||||||
|
flagSyncMarkers = 1 << iota // file format contains sync markers
|
||||||
|
)
|
21
vendor/golang.org/x/tools/go/internal/pkgbits/frames_go1.go
generated
vendored
Normal file
21
vendor/golang.org/x/tools/go/internal/pkgbits/frames_go1.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
//go:build !go1.7
|
||||||
|
// +build !go1.7
|
||||||
|
|
||||||
|
// TODO(mdempsky): Remove after #44505 is resolved
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
import "runtime"
|
||||||
|
|
||||||
|
func walkFrames(pcs []uintptr, visit frameVisitor) {
|
||||||
|
for _, pc := range pcs {
|
||||||
|
fn := runtime.FuncForPC(pc)
|
||||||
|
file, line := fn.FileLine(pc)
|
||||||
|
|
||||||
|
visit(file, line, fn.Name(), pc-fn.Entry())
|
||||||
|
}
|
||||||
|
}
|
28
vendor/golang.org/x/tools/go/internal/pkgbits/frames_go17.go
generated
vendored
Normal file
28
vendor/golang.org/x/tools/go/internal/pkgbits/frames_go17.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
//go:build go1.7
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
import "runtime"
|
||||||
|
|
||||||
|
// walkFrames calls visit for each call frame represented by pcs.
|
||||||
|
//
|
||||||
|
// pcs should be a slice of PCs, as returned by runtime.Callers.
|
||||||
|
func walkFrames(pcs []uintptr, visit frameVisitor) {
|
||||||
|
if len(pcs) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
frames := runtime.CallersFrames(pcs)
|
||||||
|
for {
|
||||||
|
frame, more := frames.Next()
|
||||||
|
visit(frame.File, frame.Line, frame.Function, frame.PC-frame.Entry)
|
||||||
|
if !more {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
vendor/golang.org/x/tools/go/internal/pkgbits/reloc.go
generated
vendored
Normal file
42
vendor/golang.org/x/tools/go/internal/pkgbits/reloc.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
// A RelocKind indicates a particular section within a unified IR export.
|
||||||
|
type RelocKind int
|
||||||
|
|
||||||
|
// An Index represents a bitstream element index within a particular
|
||||||
|
// section.
|
||||||
|
type Index int
|
||||||
|
|
||||||
|
// A relocEnt (relocation entry) is an entry in an element's local
|
||||||
|
// reference table.
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): Rename this too.
|
||||||
|
type RelocEnt struct {
|
||||||
|
Kind RelocKind
|
||||||
|
Idx Index
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserved indices within the meta relocation section.
|
||||||
|
const (
|
||||||
|
PublicRootIdx Index = 0
|
||||||
|
PrivateRootIdx Index = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RelocString RelocKind = iota
|
||||||
|
RelocMeta
|
||||||
|
RelocPosBase
|
||||||
|
RelocPkg
|
||||||
|
RelocName
|
||||||
|
RelocType
|
||||||
|
RelocObj
|
||||||
|
RelocObjExt
|
||||||
|
RelocObjDict
|
||||||
|
RelocBody
|
||||||
|
|
||||||
|
numRelocs = iota
|
||||||
|
)
|
17
vendor/golang.org/x/tools/go/internal/pkgbits/support.go
generated
vendored
Normal file
17
vendor/golang.org/x/tools/go/internal/pkgbits/support.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func assert(b bool) {
|
||||||
|
if !b {
|
||||||
|
panic("assertion failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorf(format string, args ...interface{}) {
|
||||||
|
panic(fmt.Errorf(format, args...))
|
||||||
|
}
|
113
vendor/golang.org/x/tools/go/internal/pkgbits/sync.go
generated
vendored
Normal file
113
vendor/golang.org/x/tools/go/internal/pkgbits/sync.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// fmtFrames formats a backtrace for reporting reader/writer desyncs.
|
||||||
|
func fmtFrames(pcs ...uintptr) []string {
|
||||||
|
res := make([]string, 0, len(pcs))
|
||||||
|
walkFrames(pcs, func(file string, line int, name string, offset uintptr) {
|
||||||
|
// Trim package from function name. It's just redundant noise.
|
||||||
|
name = strings.TrimPrefix(name, "cmd/compile/internal/noder.")
|
||||||
|
|
||||||
|
res = append(res, fmt.Sprintf("%s:%v: %s +0x%v", file, line, name, offset))
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
type frameVisitor func(file string, line int, name string, offset uintptr)
|
||||||
|
|
||||||
|
// SyncMarker is an enum type that represents markers that may be
|
||||||
|
// written to export data to ensure the reader and writer stay
|
||||||
|
// synchronized.
|
||||||
|
type SyncMarker int
|
||||||
|
|
||||||
|
//go:generate stringer -type=SyncMarker -trimprefix=Sync
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ SyncMarker = iota
|
||||||
|
|
||||||
|
// Public markers (known to go/types importers).
|
||||||
|
|
||||||
|
// Low-level coding markers.
|
||||||
|
SyncEOF
|
||||||
|
SyncBool
|
||||||
|
SyncInt64
|
||||||
|
SyncUint64
|
||||||
|
SyncString
|
||||||
|
SyncValue
|
||||||
|
SyncVal
|
||||||
|
SyncRelocs
|
||||||
|
SyncReloc
|
||||||
|
SyncUseReloc
|
||||||
|
|
||||||
|
// Higher-level object and type markers.
|
||||||
|
SyncPublic
|
||||||
|
SyncPos
|
||||||
|
SyncPosBase
|
||||||
|
SyncObject
|
||||||
|
SyncObject1
|
||||||
|
SyncPkg
|
||||||
|
SyncPkgDef
|
||||||
|
SyncMethod
|
||||||
|
SyncType
|
||||||
|
SyncTypeIdx
|
||||||
|
SyncTypeParamNames
|
||||||
|
SyncSignature
|
||||||
|
SyncParams
|
||||||
|
SyncParam
|
||||||
|
SyncCodeObj
|
||||||
|
SyncSym
|
||||||
|
SyncLocalIdent
|
||||||
|
SyncSelector
|
||||||
|
|
||||||
|
// Private markers (only known to cmd/compile).
|
||||||
|
SyncPrivate
|
||||||
|
|
||||||
|
SyncFuncExt
|
||||||
|
SyncVarExt
|
||||||
|
SyncTypeExt
|
||||||
|
SyncPragma
|
||||||
|
|
||||||
|
SyncExprList
|
||||||
|
SyncExprs
|
||||||
|
SyncExpr
|
||||||
|
SyncExprType
|
||||||
|
SyncAssign
|
||||||
|
SyncOp
|
||||||
|
SyncFuncLit
|
||||||
|
SyncCompLit
|
||||||
|
|
||||||
|
SyncDecl
|
||||||
|
SyncFuncBody
|
||||||
|
SyncOpenScope
|
||||||
|
SyncCloseScope
|
||||||
|
SyncCloseAnotherScope
|
||||||
|
SyncDeclNames
|
||||||
|
SyncDeclName
|
||||||
|
|
||||||
|
SyncStmts
|
||||||
|
SyncBlockStmt
|
||||||
|
SyncIfStmt
|
||||||
|
SyncForStmt
|
||||||
|
SyncSwitchStmt
|
||||||
|
SyncRangeStmt
|
||||||
|
SyncCaseClause
|
||||||
|
SyncCommClause
|
||||||
|
SyncSelectStmt
|
||||||
|
SyncDecls
|
||||||
|
SyncLabeledStmt
|
||||||
|
SyncUseObjLocal
|
||||||
|
SyncAddLocal
|
||||||
|
SyncLinkname
|
||||||
|
SyncStmt1
|
||||||
|
SyncStmtsEnd
|
||||||
|
SyncLabel
|
||||||
|
SyncOptLabel
|
||||||
|
)
|
89
vendor/golang.org/x/tools/go/internal/pkgbits/syncmarker_string.go
generated
vendored
Normal file
89
vendor/golang.org/x/tools/go/internal/pkgbits/syncmarker_string.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// Code generated by "stringer -type=SyncMarker -trimprefix=Sync"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[SyncEOF-1]
|
||||||
|
_ = x[SyncBool-2]
|
||||||
|
_ = x[SyncInt64-3]
|
||||||
|
_ = x[SyncUint64-4]
|
||||||
|
_ = x[SyncString-5]
|
||||||
|
_ = x[SyncValue-6]
|
||||||
|
_ = x[SyncVal-7]
|
||||||
|
_ = x[SyncRelocs-8]
|
||||||
|
_ = x[SyncReloc-9]
|
||||||
|
_ = x[SyncUseReloc-10]
|
||||||
|
_ = x[SyncPublic-11]
|
||||||
|
_ = x[SyncPos-12]
|
||||||
|
_ = x[SyncPosBase-13]
|
||||||
|
_ = x[SyncObject-14]
|
||||||
|
_ = x[SyncObject1-15]
|
||||||
|
_ = x[SyncPkg-16]
|
||||||
|
_ = x[SyncPkgDef-17]
|
||||||
|
_ = x[SyncMethod-18]
|
||||||
|
_ = x[SyncType-19]
|
||||||
|
_ = x[SyncTypeIdx-20]
|
||||||
|
_ = x[SyncTypeParamNames-21]
|
||||||
|
_ = x[SyncSignature-22]
|
||||||
|
_ = x[SyncParams-23]
|
||||||
|
_ = x[SyncParam-24]
|
||||||
|
_ = x[SyncCodeObj-25]
|
||||||
|
_ = x[SyncSym-26]
|
||||||
|
_ = x[SyncLocalIdent-27]
|
||||||
|
_ = x[SyncSelector-28]
|
||||||
|
_ = x[SyncPrivate-29]
|
||||||
|
_ = x[SyncFuncExt-30]
|
||||||
|
_ = x[SyncVarExt-31]
|
||||||
|
_ = x[SyncTypeExt-32]
|
||||||
|
_ = x[SyncPragma-33]
|
||||||
|
_ = x[SyncExprList-34]
|
||||||
|
_ = x[SyncExprs-35]
|
||||||
|
_ = x[SyncExpr-36]
|
||||||
|
_ = x[SyncExprType-37]
|
||||||
|
_ = x[SyncAssign-38]
|
||||||
|
_ = x[SyncOp-39]
|
||||||
|
_ = x[SyncFuncLit-40]
|
||||||
|
_ = x[SyncCompLit-41]
|
||||||
|
_ = x[SyncDecl-42]
|
||||||
|
_ = x[SyncFuncBody-43]
|
||||||
|
_ = x[SyncOpenScope-44]
|
||||||
|
_ = x[SyncCloseScope-45]
|
||||||
|
_ = x[SyncCloseAnotherScope-46]
|
||||||
|
_ = x[SyncDeclNames-47]
|
||||||
|
_ = x[SyncDeclName-48]
|
||||||
|
_ = x[SyncStmts-49]
|
||||||
|
_ = x[SyncBlockStmt-50]
|
||||||
|
_ = x[SyncIfStmt-51]
|
||||||
|
_ = x[SyncForStmt-52]
|
||||||
|
_ = x[SyncSwitchStmt-53]
|
||||||
|
_ = x[SyncRangeStmt-54]
|
||||||
|
_ = x[SyncCaseClause-55]
|
||||||
|
_ = x[SyncCommClause-56]
|
||||||
|
_ = x[SyncSelectStmt-57]
|
||||||
|
_ = x[SyncDecls-58]
|
||||||
|
_ = x[SyncLabeledStmt-59]
|
||||||
|
_ = x[SyncUseObjLocal-60]
|
||||||
|
_ = x[SyncAddLocal-61]
|
||||||
|
_ = x[SyncLinkname-62]
|
||||||
|
_ = x[SyncStmt1-63]
|
||||||
|
_ = x[SyncStmtsEnd-64]
|
||||||
|
_ = x[SyncLabel-65]
|
||||||
|
_ = x[SyncOptLabel-66]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _SyncMarker_name = "EOFBoolInt64Uint64StringValueValRelocsRelocUseRelocPublicPosPosBaseObjectObject1PkgPkgDefMethodTypeTypeIdxTypeParamNamesSignatureParamsParamCodeObjSymLocalIdentSelectorPrivateFuncExtVarExtTypeExtPragmaExprListExprsExprExprTypeAssignOpFuncLitCompLitDeclFuncBodyOpenScopeCloseScopeCloseAnotherScopeDeclNamesDeclNameStmtsBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtUseObjLocalAddLocalLinknameStmt1StmtsEndLabelOptLabel"
|
||||||
|
|
||||||
|
var _SyncMarker_index = [...]uint16{0, 3, 7, 12, 18, 24, 29, 32, 38, 43, 51, 57, 60, 67, 73, 80, 83, 89, 95, 99, 106, 120, 129, 135, 140, 147, 150, 160, 168, 175, 182, 188, 195, 201, 209, 214, 218, 226, 232, 234, 241, 248, 252, 260, 269, 279, 296, 305, 313, 318, 327, 333, 340, 350, 359, 369, 379, 389, 394, 405, 416, 424, 432, 437, 445, 450, 458}
|
||||||
|
|
||||||
|
func (i SyncMarker) String() string {
|
||||||
|
i -= 1
|
||||||
|
if i < 0 || i >= SyncMarker(len(_SyncMarker_index)-1) {
|
||||||
|
return "SyncMarker(" + strconv.FormatInt(int64(i+1), 10) + ")"
|
||||||
|
}
|
||||||
|
return _SyncMarker_name[_SyncMarker_index[i]:_SyncMarker_index[i+1]]
|
||||||
|
}
|
220
vendor/golang.org/x/tools/go/packages/doc.go
generated
vendored
Normal file
220
vendor/golang.org/x/tools/go/packages/doc.go
generated
vendored
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package packages loads Go packages for inspection and analysis.
|
||||||
|
|
||||||
|
The Load function takes as input a list of patterns and return a list of Package
|
||||||
|
structs describing individual packages matched by those patterns.
|
||||||
|
The LoadMode controls the amount of detail in the loaded packages.
|
||||||
|
|
||||||
|
Load passes most patterns directly to the underlying build tool,
|
||||||
|
but all patterns with the prefix "query=", where query is a
|
||||||
|
non-empty string of letters from [a-z], are reserved and may be
|
||||||
|
interpreted as query operators.
|
||||||
|
|
||||||
|
Two query operators are currently supported: "file" and "pattern".
|
||||||
|
|
||||||
|
The query "file=path/to/file.go" matches the package or packages enclosing
|
||||||
|
the Go source file path/to/file.go. For example "file=~/go/src/fmt/print.go"
|
||||||
|
might return the packages "fmt" and "fmt [fmt.test]".
|
||||||
|
|
||||||
|
The query "pattern=string" causes "string" to be passed directly to
|
||||||
|
the underlying build tool. In most cases this is unnecessary,
|
||||||
|
but an application can use Load("pattern=" + x) as an escaping mechanism
|
||||||
|
to ensure that x is not interpreted as a query operator if it contains '='.
|
||||||
|
|
||||||
|
All other query operators are reserved for future use and currently
|
||||||
|
cause Load to report an error.
|
||||||
|
|
||||||
|
The Package struct provides basic information about the package, including
|
||||||
|
|
||||||
|
- ID, a unique identifier for the package in the returned set;
|
||||||
|
- GoFiles, the names of the package's Go source files;
|
||||||
|
- Imports, a map from source import strings to the Packages they name;
|
||||||
|
- Types, the type information for the package's exported symbols;
|
||||||
|
- Syntax, the parsed syntax trees for the package's source code; and
|
||||||
|
- TypeInfo, the result of a complete type-check of the package syntax trees.
|
||||||
|
|
||||||
|
(See the documentation for type Package for the complete list of fields
|
||||||
|
and more detailed descriptions.)
|
||||||
|
|
||||||
|
For example,
|
||||||
|
|
||||||
|
Load(nil, "bytes", "unicode...")
|
||||||
|
|
||||||
|
returns four Package structs describing the standard library packages
|
||||||
|
bytes, unicode, unicode/utf16, and unicode/utf8. Note that one pattern
|
||||||
|
can match multiple packages and that a package might be matched by
|
||||||
|
multiple patterns: in general it is not possible to determine which
|
||||||
|
packages correspond to which patterns.
|
||||||
|
|
||||||
|
Note that the list returned by Load contains only the packages matched
|
||||||
|
by the patterns. Their dependencies can be found by walking the import
|
||||||
|
graph using the Imports fields.
|
||||||
|
|
||||||
|
The Load function can be configured by passing a pointer to a Config as
|
||||||
|
the first argument. A nil Config is equivalent to the zero Config, which
|
||||||
|
causes Load to run in LoadFiles mode, collecting minimal information.
|
||||||
|
See the documentation for type Config for details.
|
||||||
|
|
||||||
|
As noted earlier, the Config.Mode controls the amount of detail
|
||||||
|
reported about the loaded packages. See the documentation for type LoadMode
|
||||||
|
for details.
|
||||||
|
|
||||||
|
Most tools should pass their command-line arguments (after any flags)
|
||||||
|
uninterpreted to the loader, so that the loader can interpret them
|
||||||
|
according to the conventions of the underlying build system.
|
||||||
|
See the Example function for typical usage.
|
||||||
|
*/
|
||||||
|
package packages // import "golang.org/x/tools/go/packages"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Motivation and design considerations
|
||||||
|
|
||||||
|
The new package's design solves problems addressed by two existing
|
||||||
|
packages: go/build, which locates and describes packages, and
|
||||||
|
golang.org/x/tools/go/loader, which loads, parses and type-checks them.
|
||||||
|
The go/build.Package structure encodes too much of the 'go build' way
|
||||||
|
of organizing projects, leaving us in need of a data type that describes a
|
||||||
|
package of Go source code independent of the underlying build system.
|
||||||
|
We wanted something that works equally well with go build and vgo, and
|
||||||
|
also other build systems such as Bazel and Blaze, making it possible to
|
||||||
|
construct analysis tools that work in all these environments.
|
||||||
|
Tools such as errcheck and staticcheck were essentially unavailable to
|
||||||
|
the Go community at Google, and some of Google's internal tools for Go
|
||||||
|
are unavailable externally.
|
||||||
|
This new package provides a uniform way to obtain package metadata by
|
||||||
|
querying each of these build systems, optionally supporting their
|
||||||
|
preferred command-line notations for packages, so that tools integrate
|
||||||
|
neatly with users' build environments. The Metadata query function
|
||||||
|
executes an external query tool appropriate to the current workspace.
|
||||||
|
|
||||||
|
Loading packages always returns the complete import graph "all the way down",
|
||||||
|
even if all you want is information about a single package, because the query
|
||||||
|
mechanisms of all the build systems we currently support ({go,vgo} list, and
|
||||||
|
blaze/bazel aspect-based query) cannot provide detailed information
|
||||||
|
about one package without visiting all its dependencies too, so there is
|
||||||
|
no additional asymptotic cost to providing transitive information.
|
||||||
|
(This property might not be true of a hypothetical 5th build system.)
|
||||||
|
|
||||||
|
In calls to TypeCheck, all initial packages, and any package that
|
||||||
|
transitively depends on one of them, must be loaded from source.
|
||||||
|
Consider A->B->C->D->E: if A,C are initial, A,B,C must be loaded from
|
||||||
|
source; D may be loaded from export data, and E may not be loaded at all
|
||||||
|
(though it's possible that D's export data mentions it, so a
|
||||||
|
types.Package may be created for it and exposed.)
|
||||||
|
|
||||||
|
The old loader had a feature to suppress type-checking of function
|
||||||
|
bodies on a per-package basis, primarily intended to reduce the work of
|
||||||
|
obtaining type information for imported packages. Now that imports are
|
||||||
|
satisfied by export data, the optimization no longer seems necessary.
|
||||||
|
|
||||||
|
Despite some early attempts, the old loader did not exploit export data,
|
||||||
|
instead always using the equivalent of WholeProgram mode. This was due
|
||||||
|
to the complexity of mixing source and export data packages (now
|
||||||
|
resolved by the upward traversal mentioned above), and because export data
|
||||||
|
files were nearly always missing or stale. Now that 'go build' supports
|
||||||
|
caching, all the underlying build systems can guarantee to produce
|
||||||
|
export data in a reasonable (amortized) time.
|
||||||
|
|
||||||
|
Test "main" packages synthesized by the build system are now reported as
|
||||||
|
first-class packages, avoiding the need for clients (such as go/ssa) to
|
||||||
|
reinvent this generation logic.
|
||||||
|
|
||||||
|
One way in which go/packages is simpler than the old loader is in its
|
||||||
|
treatment of in-package tests. In-package tests are packages that
|
||||||
|
consist of all the files of the library under test, plus the test files.
|
||||||
|
The old loader constructed in-package tests by a two-phase process of
|
||||||
|
mutation called "augmentation": first it would construct and type check
|
||||||
|
all the ordinary library packages and type-check the packages that
|
||||||
|
depend on them; then it would add more (test) files to the package and
|
||||||
|
type-check again. This two-phase approach had four major problems:
|
||||||
|
1) in processing the tests, the loader modified the library package,
|
||||||
|
leaving no way for a client application to see both the test
|
||||||
|
package and the library package; one would mutate into the other.
|
||||||
|
2) because test files can declare additional methods on types defined in
|
||||||
|
the library portion of the package, the dispatch of method calls in
|
||||||
|
the library portion was affected by the presence of the test files.
|
||||||
|
This should have been a clue that the packages were logically
|
||||||
|
different.
|
||||||
|
3) this model of "augmentation" assumed at most one in-package test
|
||||||
|
per library package, which is true of projects using 'go build',
|
||||||
|
but not other build systems.
|
||||||
|
4) because of the two-phase nature of test processing, all packages that
|
||||||
|
import the library package had to be processed before augmentation,
|
||||||
|
forcing a "one-shot" API and preventing the client from calling Load
|
||||||
|
in several times in sequence as is now possible in WholeProgram mode.
|
||||||
|
(TypeCheck mode has a similar one-shot restriction for a different reason.)
|
||||||
|
|
||||||
|
Early drafts of this package supported "multi-shot" operation.
|
||||||
|
Although it allowed clients to make a sequence of calls (or concurrent
|
||||||
|
calls) to Load, building up the graph of Packages incrementally,
|
||||||
|
it was of marginal value: it complicated the API
|
||||||
|
(since it allowed some options to vary across calls but not others),
|
||||||
|
it complicated the implementation,
|
||||||
|
it cannot be made to work in Types mode, as explained above,
|
||||||
|
and it was less efficient than making one combined call (when this is possible).
|
||||||
|
Among the clients we have inspected, none made multiple calls to load
|
||||||
|
but could not be easily and satisfactorily modified to make only a single call.
|
||||||
|
However, applications changes may be required.
|
||||||
|
For example, the ssadump command loads the user-specified packages
|
||||||
|
and in addition the runtime package. It is tempting to simply append
|
||||||
|
"runtime" to the user-provided list, but that does not work if the user
|
||||||
|
specified an ad-hoc package such as [a.go b.go].
|
||||||
|
Instead, ssadump no longer requests the runtime package,
|
||||||
|
but seeks it among the dependencies of the user-specified packages,
|
||||||
|
and emits an error if it is not found.
|
||||||
|
|
||||||
|
Overlays: The Overlay field in the Config allows providing alternate contents
|
||||||
|
for Go source files, by providing a mapping from file path to contents.
|
||||||
|
go/packages will pull in new imports added in overlay files when go/packages
|
||||||
|
is run in LoadImports mode or greater.
|
||||||
|
Overlay support for the go list driver isn't complete yet: if the file doesn't
|
||||||
|
exist on disk, it will only be recognized in an overlay if it is a non-test file
|
||||||
|
and the package would be reported even without the overlay.
|
||||||
|
|
||||||
|
Questions & Tasks
|
||||||
|
|
||||||
|
- Add GOARCH/GOOS?
|
||||||
|
They are not portable concepts, but could be made portable.
|
||||||
|
Our goal has been to allow users to express themselves using the conventions
|
||||||
|
of the underlying build system: if the build system honors GOARCH
|
||||||
|
during a build and during a metadata query, then so should
|
||||||
|
applications built atop that query mechanism.
|
||||||
|
Conversely, if the target architecture of the build is determined by
|
||||||
|
command-line flags, the application can pass the relevant
|
||||||
|
flags through to the build system using a command such as:
|
||||||
|
myapp -query_flag="--cpu=amd64" -query_flag="--os=darwin"
|
||||||
|
However, this approach is low-level, unwieldy, and non-portable.
|
||||||
|
GOOS and GOARCH seem important enough to warrant a dedicated option.
|
||||||
|
|
||||||
|
- How should we handle partial failures such as a mixture of good and
|
||||||
|
malformed patterns, existing and non-existent packages, successful and
|
||||||
|
failed builds, import failures, import cycles, and so on, in a call to
|
||||||
|
Load?
|
||||||
|
|
||||||
|
- Support bazel, blaze, and go1.10 list, not just go1.11 list.
|
||||||
|
|
||||||
|
- Handle (and test) various partial success cases, e.g.
|
||||||
|
a mixture of good packages and:
|
||||||
|
invalid patterns
|
||||||
|
nonexistent packages
|
||||||
|
empty packages
|
||||||
|
packages with malformed package or import declarations
|
||||||
|
unreadable files
|
||||||
|
import cycles
|
||||||
|
other parse errors
|
||||||
|
type errors
|
||||||
|
Make sure we record errors at the correct place in the graph.
|
||||||
|
|
||||||
|
- Missing packages among initial arguments are not reported.
|
||||||
|
Return bogus packages for them, like golist does.
|
||||||
|
|
||||||
|
- "undeclared name" errors (for example) are reported out of source file
|
||||||
|
order. I suspect this is due to the breadth-first resolution now used
|
||||||
|
by go/types. Is that a bug? Discuss with gri.
|
||||||
|
|
||||||
|
*/
|
101
vendor/golang.org/x/tools/go/packages/external.go
generated
vendored
Normal file
101
vendor/golang.org/x/tools/go/packages/external.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This file enables an external tool to intercept package requests.
|
||||||
|
// If the tool is present then its results are used in preference to
|
||||||
|
// the go list command.
|
||||||
|
|
||||||
|
package packages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
exec "golang.org/x/sys/execabs"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The Driver Protocol
|
||||||
|
//
|
||||||
|
// The driver, given the inputs to a call to Load, returns metadata about the packages specified.
|
||||||
|
// This allows for different build systems to support go/packages by telling go/packages how the
|
||||||
|
// packages' source is organized.
|
||||||
|
// The driver is a binary, either specified by the GOPACKAGESDRIVER environment variable or in
|
||||||
|
// the path as gopackagesdriver. It's given the inputs to load in its argv. See the package
|
||||||
|
// documentation in doc.go for the full description of the patterns that need to be supported.
|
||||||
|
// A driver receives as a JSON-serialized driverRequest struct in standard input and will
|
||||||
|
// produce a JSON-serialized driverResponse (see definition in packages.go) in its standard output.
|
||||||
|
|
||||||
|
// driverRequest is used to provide the portion of Load's Config that is needed by a driver.
|
||||||
|
type driverRequest struct {
|
||||||
|
Mode LoadMode `json:"mode"`
|
||||||
|
// Env specifies the environment the underlying build system should be run in.
|
||||||
|
Env []string `json:"env"`
|
||||||
|
// BuildFlags are flags that should be passed to the underlying build system.
|
||||||
|
BuildFlags []string `json:"build_flags"`
|
||||||
|
// Tests specifies whether the patterns should also return test packages.
|
||||||
|
Tests bool `json:"tests"`
|
||||||
|
// Overlay maps file paths (relative to the driver's working directory) to the byte contents
|
||||||
|
// of overlay files.
|
||||||
|
Overlay map[string][]byte `json:"overlay"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// findExternalDriver returns the file path of a tool that supplies
|
||||||
|
// the build system package structure, or "" if not found."
|
||||||
|
// If GOPACKAGESDRIVER is set in the environment findExternalTool returns its
|
||||||
|
// value, otherwise it searches for a binary named gopackagesdriver on the PATH.
|
||||||
|
func findExternalDriver(cfg *Config) driver {
|
||||||
|
const toolPrefix = "GOPACKAGESDRIVER="
|
||||||
|
tool := ""
|
||||||
|
for _, env := range cfg.Env {
|
||||||
|
if val := strings.TrimPrefix(env, toolPrefix); val != env {
|
||||||
|
tool = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tool != "" && tool == "off" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if tool == "" {
|
||||||
|
var err error
|
||||||
|
tool, err = exec.LookPath("gopackagesdriver")
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return func(cfg *Config, words ...string) (*driverResponse, error) {
|
||||||
|
req, err := json.Marshal(driverRequest{
|
||||||
|
Mode: cfg.Mode,
|
||||||
|
Env: cfg.Env,
|
||||||
|
BuildFlags: cfg.BuildFlags,
|
||||||
|
Tests: cfg.Tests,
|
||||||
|
Overlay: cfg.Overlay,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to encode message to driver tool: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
stderr := new(bytes.Buffer)
|
||||||
|
cmd := exec.CommandContext(cfg.Context, tool, words...)
|
||||||
|
cmd.Dir = cfg.Dir
|
||||||
|
cmd.Env = cfg.Env
|
||||||
|
cmd.Stdin = bytes.NewReader(req)
|
||||||
|
cmd.Stdout = buf
|
||||||
|
cmd.Stderr = stderr
|
||||||
|
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return nil, fmt.Errorf("%v: %v: %s", tool, err, cmd.Stderr)
|
||||||
|
}
|
||||||
|
if len(stderr.Bytes()) != 0 && os.Getenv("GOPACKAGESPRINTDRIVERERRORS") != "" {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
var response driverResponse
|
||||||
|
if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &response, nil
|
||||||
|
}
|
||||||
|
}
|
1173
vendor/golang.org/x/tools/go/packages/golist.go
generated
vendored
Normal file
1173
vendor/golang.org/x/tools/go/packages/golist.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
575
vendor/golang.org/x/tools/go/packages/golist_overlay.go
generated
vendored
Normal file
575
vendor/golang.org/x/tools/go/packages/golist_overlay.go
generated
vendored
Normal file
@ -0,0 +1,575 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package packages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/gocommand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// processGolistOverlay provides rudimentary support for adding
|
||||||
|
// files that don't exist on disk to an overlay. The results can be
|
||||||
|
// sometimes incorrect.
|
||||||
|
// TODO(matloob): Handle unsupported cases, including the following:
|
||||||
|
// - determining the correct package to add given a new import path
|
||||||
|
func (state *golistState) processGolistOverlay(response *responseDeduper) (modifiedPkgs, needPkgs []string, err error) {
|
||||||
|
havePkgs := make(map[string]string) // importPath -> non-test package ID
|
||||||
|
needPkgsSet := make(map[string]bool)
|
||||||
|
modifiedPkgsSet := make(map[string]bool)
|
||||||
|
|
||||||
|
pkgOfDir := make(map[string][]*Package)
|
||||||
|
for _, pkg := range response.dr.Packages {
|
||||||
|
// This is an approximation of import path to id. This can be
|
||||||
|
// wrong for tests, vendored packages, and a number of other cases.
|
||||||
|
havePkgs[pkg.PkgPath] = pkg.ID
|
||||||
|
dir, err := commonDir(pkg.GoFiles)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if dir != "" {
|
||||||
|
pkgOfDir[dir] = append(pkgOfDir[dir], pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no new imports are added, it is safe to avoid loading any needPkgs.
|
||||||
|
// Otherwise, it's hard to tell which package is actually being loaded
|
||||||
|
// (due to vendoring) and whether any modified package will show up
|
||||||
|
// in the transitive set of dependencies (because new imports are added,
|
||||||
|
// potentially modifying the transitive set of dependencies).
|
||||||
|
var overlayAddsImports bool
|
||||||
|
|
||||||
|
// If both a package and its test package are created by the overlay, we
|
||||||
|
// need the real package first. Process all non-test files before test
|
||||||
|
// files, and make the whole process deterministic while we're at it.
|
||||||
|
var overlayFiles []string
|
||||||
|
for opath := range state.cfg.Overlay {
|
||||||
|
overlayFiles = append(overlayFiles, opath)
|
||||||
|
}
|
||||||
|
sort.Slice(overlayFiles, func(i, j int) bool {
|
||||||
|
iTest := strings.HasSuffix(overlayFiles[i], "_test.go")
|
||||||
|
jTest := strings.HasSuffix(overlayFiles[j], "_test.go")
|
||||||
|
if iTest != jTest {
|
||||||
|
return !iTest // non-tests are before tests.
|
||||||
|
}
|
||||||
|
return overlayFiles[i] < overlayFiles[j]
|
||||||
|
})
|
||||||
|
for _, opath := range overlayFiles {
|
||||||
|
contents := state.cfg.Overlay[opath]
|
||||||
|
base := filepath.Base(opath)
|
||||||
|
dir := filepath.Dir(opath)
|
||||||
|
var pkg *Package // if opath belongs to both a package and its test variant, this will be the test variant
|
||||||
|
var testVariantOf *Package // if opath is a test file, this is the package it is testing
|
||||||
|
var fileExists bool
|
||||||
|
isTestFile := strings.HasSuffix(opath, "_test.go")
|
||||||
|
pkgName, ok := extractPackageName(opath, contents)
|
||||||
|
if !ok {
|
||||||
|
// Don't bother adding a file that doesn't even have a parsable package statement
|
||||||
|
// to the overlay.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// If all the overlay files belong to a different package, change the
|
||||||
|
// package name to that package.
|
||||||
|
maybeFixPackageName(pkgName, isTestFile, pkgOfDir[dir])
|
||||||
|
nextPackage:
|
||||||
|
for _, p := range response.dr.Packages {
|
||||||
|
if pkgName != p.Name && p.ID != "command-line-arguments" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, f := range p.GoFiles {
|
||||||
|
if !sameFile(filepath.Dir(f), dir) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Make sure to capture information on the package's test variant, if needed.
|
||||||
|
if isTestFile && !hasTestFiles(p) {
|
||||||
|
// TODO(matloob): Are there packages other than the 'production' variant
|
||||||
|
// of a package that this can match? This shouldn't match the test main package
|
||||||
|
// because the file is generated in another directory.
|
||||||
|
testVariantOf = p
|
||||||
|
continue nextPackage
|
||||||
|
} else if !isTestFile && hasTestFiles(p) {
|
||||||
|
// We're examining a test variant, but the overlaid file is
|
||||||
|
// a non-test file. Because the overlay implementation
|
||||||
|
// (currently) only adds a file to one package, skip this
|
||||||
|
// package, so that we can add the file to the production
|
||||||
|
// variant of the package. (https://golang.org/issue/36857
|
||||||
|
// tracks handling overlays on both the production and test
|
||||||
|
// variant of a package).
|
||||||
|
continue nextPackage
|
||||||
|
}
|
||||||
|
if pkg != nil && p != pkg && pkg.PkgPath == p.PkgPath {
|
||||||
|
// We have already seen the production version of the
|
||||||
|
// for which p is a test variant.
|
||||||
|
if hasTestFiles(p) {
|
||||||
|
testVariantOf = pkg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pkg = p
|
||||||
|
if filepath.Base(f) == base {
|
||||||
|
fileExists = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The overlay could have included an entirely new package or an
|
||||||
|
// ad-hoc package. An ad-hoc package is one that we have manually
|
||||||
|
// constructed from inadequate `go list` results for a file= query.
|
||||||
|
// It will have the ID command-line-arguments.
|
||||||
|
if pkg == nil || pkg.ID == "command-line-arguments" {
|
||||||
|
// Try to find the module or gopath dir the file is contained in.
|
||||||
|
// Then for modules, add the module opath to the beginning.
|
||||||
|
pkgPath, ok, err := state.getPkgPath(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
var forTest string // only set for x tests
|
||||||
|
isXTest := strings.HasSuffix(pkgName, "_test")
|
||||||
|
if isXTest {
|
||||||
|
forTest = pkgPath
|
||||||
|
pkgPath += "_test"
|
||||||
|
}
|
||||||
|
id := pkgPath
|
||||||
|
if isTestFile {
|
||||||
|
if isXTest {
|
||||||
|
id = fmt.Sprintf("%s [%s.test]", pkgPath, forTest)
|
||||||
|
} else {
|
||||||
|
id = fmt.Sprintf("%s [%s.test]", pkgPath, pkgPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pkg != nil {
|
||||||
|
// TODO(rstambler): We should change the package's path and ID
|
||||||
|
// here. The only issue is that this messes with the roots.
|
||||||
|
} else {
|
||||||
|
// Try to reclaim a package with the same ID, if it exists in the response.
|
||||||
|
for _, p := range response.dr.Packages {
|
||||||
|
if reclaimPackage(p, id, opath, contents) {
|
||||||
|
pkg = p
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise, create a new package.
|
||||||
|
if pkg == nil {
|
||||||
|
pkg = &Package{
|
||||||
|
PkgPath: pkgPath,
|
||||||
|
ID: id,
|
||||||
|
Name: pkgName,
|
||||||
|
Imports: make(map[string]*Package),
|
||||||
|
}
|
||||||
|
response.addPackage(pkg)
|
||||||
|
havePkgs[pkg.PkgPath] = id
|
||||||
|
// Add the production package's sources for a test variant.
|
||||||
|
if isTestFile && !isXTest && testVariantOf != nil {
|
||||||
|
pkg.GoFiles = append(pkg.GoFiles, testVariantOf.GoFiles...)
|
||||||
|
pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, testVariantOf.CompiledGoFiles...)
|
||||||
|
// Add the package under test and its imports to the test variant.
|
||||||
|
pkg.forTest = testVariantOf.PkgPath
|
||||||
|
for k, v := range testVariantOf.Imports {
|
||||||
|
pkg.Imports[k] = &Package{ID: v.ID}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isXTest {
|
||||||
|
pkg.forTest = forTest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !fileExists {
|
||||||
|
pkg.GoFiles = append(pkg.GoFiles, opath)
|
||||||
|
// TODO(matloob): Adding the file to CompiledGoFiles can exhibit the wrong behavior
|
||||||
|
// if the file will be ignored due to its build tags.
|
||||||
|
pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, opath)
|
||||||
|
modifiedPkgsSet[pkg.ID] = true
|
||||||
|
}
|
||||||
|
imports, err := extractImports(opath, contents)
|
||||||
|
if err != nil {
|
||||||
|
// Let the parser or type checker report errors later.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, imp := range imports {
|
||||||
|
// TODO(rstambler): If the package is an x test and the import has
|
||||||
|
// a test variant, make sure to replace it.
|
||||||
|
if _, found := pkg.Imports[imp]; found {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
overlayAddsImports = true
|
||||||
|
id, ok := havePkgs[imp]
|
||||||
|
if !ok {
|
||||||
|
var err error
|
||||||
|
id, err = state.resolveImport(dir, imp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pkg.Imports[imp] = &Package{ID: id}
|
||||||
|
// Add dependencies to the non-test variant version of this package as well.
|
||||||
|
if testVariantOf != nil {
|
||||||
|
testVariantOf.Imports[imp] = &Package{ID: id}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// toPkgPath guesses the package path given the id.
|
||||||
|
toPkgPath := func(sourceDir, id string) (string, error) {
|
||||||
|
if i := strings.IndexByte(id, ' '); i >= 0 {
|
||||||
|
return state.resolveImport(sourceDir, id[:i])
|
||||||
|
}
|
||||||
|
return state.resolveImport(sourceDir, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that new packages have been created, do another pass to determine
|
||||||
|
// the new set of missing packages.
|
||||||
|
for _, pkg := range response.dr.Packages {
|
||||||
|
for _, imp := range pkg.Imports {
|
||||||
|
if len(pkg.GoFiles) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("cannot resolve imports for package %q with no Go files", pkg.PkgPath)
|
||||||
|
}
|
||||||
|
pkgPath, err := toPkgPath(filepath.Dir(pkg.GoFiles[0]), imp.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if _, ok := havePkgs[pkgPath]; !ok {
|
||||||
|
needPkgsSet[pkgPath] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if overlayAddsImports {
|
||||||
|
needPkgs = make([]string, 0, len(needPkgsSet))
|
||||||
|
for pkg := range needPkgsSet {
|
||||||
|
needPkgs = append(needPkgs, pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modifiedPkgs = make([]string, 0, len(modifiedPkgsSet))
|
||||||
|
for pkg := range modifiedPkgsSet {
|
||||||
|
modifiedPkgs = append(modifiedPkgs, pkg)
|
||||||
|
}
|
||||||
|
return modifiedPkgs, needPkgs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolveImport finds the ID of a package given its import path.
|
||||||
|
// In particular, it will find the right vendored copy when in GOPATH mode.
|
||||||
|
func (state *golistState) resolveImport(sourceDir, importPath string) (string, error) {
|
||||||
|
env, err := state.getEnv()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if env["GOMOD"] != "" {
|
||||||
|
return importPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
searchDir := sourceDir
|
||||||
|
for {
|
||||||
|
vendorDir := filepath.Join(searchDir, "vendor")
|
||||||
|
exists, ok := state.vendorDirs[vendorDir]
|
||||||
|
if !ok {
|
||||||
|
info, err := os.Stat(vendorDir)
|
||||||
|
exists = err == nil && info.IsDir()
|
||||||
|
state.vendorDirs[vendorDir] = exists
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
vendoredPath := filepath.Join(vendorDir, importPath)
|
||||||
|
if info, err := os.Stat(vendoredPath); err == nil && info.IsDir() {
|
||||||
|
// We should probably check for .go files here, but shame on anyone who fools us.
|
||||||
|
path, ok, err := state.getPkgPath(vendoredPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know we've hit the top of the filesystem when we Dir / and get /,
|
||||||
|
// or C:\ and get C:\, etc.
|
||||||
|
next := filepath.Dir(searchDir)
|
||||||
|
if next == searchDir {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
searchDir = next
|
||||||
|
}
|
||||||
|
return importPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasTestFiles(p *Package) bool {
|
||||||
|
for _, f := range p.GoFiles {
|
||||||
|
if strings.HasSuffix(f, "_test.go") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// determineRootDirs returns a mapping from absolute directories that could
|
||||||
|
// contain code to their corresponding import path prefixes.
|
||||||
|
func (state *golistState) determineRootDirs() (map[string]string, error) {
|
||||||
|
env, err := state.getEnv()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if env["GOMOD"] != "" {
|
||||||
|
state.rootsOnce.Do(func() {
|
||||||
|
state.rootDirs, state.rootDirsError = state.determineRootDirsModules()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
state.rootsOnce.Do(func() {
|
||||||
|
state.rootDirs, state.rootDirsError = state.determineRootDirsGOPATH()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return state.rootDirs, state.rootDirsError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *golistState) determineRootDirsModules() (map[string]string, error) {
|
||||||
|
// List all of the modules--the first will be the directory for the main
|
||||||
|
// module. Any replaced modules will also need to be treated as roots.
|
||||||
|
// Editing files in the module cache isn't a great idea, so we don't
|
||||||
|
// plan to ever support that.
|
||||||
|
out, err := state.invokeGo("list", "-m", "-json", "all")
|
||||||
|
if err != nil {
|
||||||
|
// 'go list all' will fail if we're outside of a module and
|
||||||
|
// GO111MODULE=on. Try falling back without 'all'.
|
||||||
|
var innerErr error
|
||||||
|
out, innerErr = state.invokeGo("list", "-m", "-json")
|
||||||
|
if innerErr != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roots := map[string]string{}
|
||||||
|
modules := map[string]string{}
|
||||||
|
var i int
|
||||||
|
for dec := json.NewDecoder(out); dec.More(); {
|
||||||
|
mod := new(gocommand.ModuleJSON)
|
||||||
|
if err := dec.Decode(mod); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if mod.Dir != "" && mod.Path != "" {
|
||||||
|
// This is a valid module; add it to the map.
|
||||||
|
absDir, err := filepath.Abs(mod.Dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
modules[absDir] = mod.Path
|
||||||
|
// The first result is the main module.
|
||||||
|
if i == 0 || mod.Replace != nil && mod.Replace.Path != "" {
|
||||||
|
roots[absDir] = mod.Path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return roots, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *golistState) determineRootDirsGOPATH() (map[string]string, error) {
|
||||||
|
m := map[string]string{}
|
||||||
|
for _, dir := range filepath.SplitList(state.mustGetEnv()["GOPATH"]) {
|
||||||
|
absDir, err := filepath.Abs(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m[filepath.Join(absDir, "src")] = ""
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractImports(filename string, contents []byte) ([]string, error) {
|
||||||
|
f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.ImportsOnly) // TODO(matloob): reuse fileset?
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var res []string
|
||||||
|
for _, imp := range f.Imports {
|
||||||
|
quotedPath := imp.Path.Value
|
||||||
|
path, err := strconv.Unquote(quotedPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res = append(res, path)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// reclaimPackage attempts to reuse a package that failed to load in an overlay.
|
||||||
|
//
|
||||||
|
// If the package has errors and has no Name, GoFiles, or Imports,
|
||||||
|
// then it's possible that it doesn't yet exist on disk.
|
||||||
|
func reclaimPackage(pkg *Package, id string, filename string, contents []byte) bool {
|
||||||
|
// TODO(rstambler): Check the message of the actual error?
|
||||||
|
// It differs between $GOPATH and module mode.
|
||||||
|
if pkg.ID != id {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(pkg.Errors) != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if pkg.Name != "" || pkg.ExportFile != "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(pkg.GoFiles) > 0 || len(pkg.CompiledGoFiles) > 0 || len(pkg.OtherFiles) > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(pkg.Imports) > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
pkgName, ok := extractPackageName(filename, contents)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
pkg.Name = pkgName
|
||||||
|
pkg.Errors = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractPackageName(filename string, contents []byte) (string, bool) {
|
||||||
|
// TODO(rstambler): Check the message of the actual error?
|
||||||
|
// It differs between $GOPATH and module mode.
|
||||||
|
f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.PackageClauseOnly) // TODO(matloob): reuse fileset?
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return f.Name.Name, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// commonDir returns the directory that all files are in, "" if files is empty,
|
||||||
|
// or an error if they aren't in the same directory.
|
||||||
|
func commonDir(files []string) (string, error) {
|
||||||
|
seen := make(map[string]bool)
|
||||||
|
for _, f := range files {
|
||||||
|
seen[filepath.Dir(f)] = true
|
||||||
|
}
|
||||||
|
if len(seen) > 1 {
|
||||||
|
return "", fmt.Errorf("files (%v) are in more than one directory: %v", files, seen)
|
||||||
|
}
|
||||||
|
for k := range seen {
|
||||||
|
// seen has only one element; return it.
|
||||||
|
return k, nil
|
||||||
|
}
|
||||||
|
return "", nil // no files
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is possible that the files in the disk directory dir have a different package
|
||||||
|
// name from newName, which is deduced from the overlays. If they all have a different
|
||||||
|
// package name, and they all have the same package name, then that name becomes
|
||||||
|
// the package name.
|
||||||
|
// It returns true if it changes the package name, false otherwise.
|
||||||
|
func maybeFixPackageName(newName string, isTestFile bool, pkgsOfDir []*Package) {
|
||||||
|
names := make(map[string]int)
|
||||||
|
for _, p := range pkgsOfDir {
|
||||||
|
names[p.Name]++
|
||||||
|
}
|
||||||
|
if len(names) != 1 {
|
||||||
|
// some files are in different packages
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var oldName string
|
||||||
|
for k := range names {
|
||||||
|
oldName = k
|
||||||
|
}
|
||||||
|
if newName == oldName {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// We might have a case where all of the package names in the directory are
|
||||||
|
// the same, but the overlay file is for an x test, which belongs to its
|
||||||
|
// own package. If the x test does not yet exist on disk, we may not yet
|
||||||
|
// have its package name on disk, but we should not rename the packages.
|
||||||
|
//
|
||||||
|
// We use a heuristic to determine if this file belongs to an x test:
|
||||||
|
// The test file should have a package name whose package name has a _test
|
||||||
|
// suffix or looks like "newName_test".
|
||||||
|
maybeXTest := strings.HasPrefix(oldName+"_test", newName) || strings.HasSuffix(newName, "_test")
|
||||||
|
if isTestFile && maybeXTest {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, p := range pkgsOfDir {
|
||||||
|
p.Name = newName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is copy-pasted from
|
||||||
|
// https://github.com/golang/go/blob/9706f510a5e2754595d716bd64be8375997311fb/src/cmd/go/internal/search/search.go#L360.
|
||||||
|
// It should be deleted when we remove support for overlays from go/packages.
|
||||||
|
//
|
||||||
|
// NOTE: This does not handle any ./... or ./ style queries, as this function
|
||||||
|
// doesn't know the working directory.
|
||||||
|
//
|
||||||
|
// matchPattern(pattern)(name) reports whether
|
||||||
|
// name matches pattern. Pattern is a limited glob
|
||||||
|
// pattern in which '...' means 'any string' and there
|
||||||
|
// is no other special syntax.
|
||||||
|
// Unfortunately, there are two special cases. Quoting "go help packages":
|
||||||
|
//
|
||||||
|
// First, /... at the end of the pattern can match an empty string,
|
||||||
|
// so that net/... matches both net and packages in its subdirectories, like net/http.
|
||||||
|
// Second, any slash-separated pattern element containing a wildcard never
|
||||||
|
// participates in a match of the "vendor" element in the path of a vendored
|
||||||
|
// package, so that ./... does not match packages in subdirectories of
|
||||||
|
// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do.
|
||||||
|
// Note, however, that a directory named vendor that itself contains code
|
||||||
|
// is not a vendored package: cmd/vendor would be a command named vendor,
|
||||||
|
// and the pattern cmd/... matches it.
|
||||||
|
func matchPattern(pattern string) func(name string) bool {
|
||||||
|
// Convert pattern to regular expression.
|
||||||
|
// The strategy for the trailing /... is to nest it in an explicit ? expression.
|
||||||
|
// The strategy for the vendor exclusion is to change the unmatchable
|
||||||
|
// vendor strings to a disallowed code point (vendorChar) and to use
|
||||||
|
// "(anything but that codepoint)*" as the implementation of the ... wildcard.
|
||||||
|
// This is a bit complicated but the obvious alternative,
|
||||||
|
// namely a hand-written search like in most shell glob matchers,
|
||||||
|
// is too easy to make accidentally exponential.
|
||||||
|
// Using package regexp guarantees linear-time matching.
|
||||||
|
|
||||||
|
const vendorChar = "\x00"
|
||||||
|
|
||||||
|
if strings.Contains(pattern, vendorChar) {
|
||||||
|
return func(name string) bool { return false }
|
||||||
|
}
|
||||||
|
|
||||||
|
re := regexp.QuoteMeta(pattern)
|
||||||
|
re = replaceVendor(re, vendorChar)
|
||||||
|
switch {
|
||||||
|
case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`):
|
||||||
|
re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)`
|
||||||
|
case re == vendorChar+`/\.\.\.`:
|
||||||
|
re = `(/vendor|/` + vendorChar + `/\.\.\.)`
|
||||||
|
case strings.HasSuffix(re, `/\.\.\.`):
|
||||||
|
re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?`
|
||||||
|
}
|
||||||
|
re = strings.ReplaceAll(re, `\.\.\.`, `[^`+vendorChar+`]*`)
|
||||||
|
|
||||||
|
reg := regexp.MustCompile(`^` + re + `$`)
|
||||||
|
|
||||||
|
return func(name string) bool {
|
||||||
|
if strings.Contains(name, vendorChar) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return reg.MatchString(replaceVendor(name, vendorChar))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// replaceVendor returns the result of replacing
|
||||||
|
// non-trailing vendor path elements in x with repl.
|
||||||
|
func replaceVendor(x, repl string) string {
|
||||||
|
if !strings.Contains(x, "vendor") {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
elem := strings.Split(x, "/")
|
||||||
|
for i := 0; i < len(elem)-1; i++ {
|
||||||
|
if elem[i] == "vendor" {
|
||||||
|
elem[i] = repl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(elem, "/")
|
||||||
|
}
|
57
vendor/golang.org/x/tools/go/packages/loadmode_string.go
generated
vendored
Normal file
57
vendor/golang.org/x/tools/go/packages/loadmode_string.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package packages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var allModes = []LoadMode{
|
||||||
|
NeedName,
|
||||||
|
NeedFiles,
|
||||||
|
NeedCompiledGoFiles,
|
||||||
|
NeedImports,
|
||||||
|
NeedDeps,
|
||||||
|
NeedExportFile,
|
||||||
|
NeedTypes,
|
||||||
|
NeedSyntax,
|
||||||
|
NeedTypesInfo,
|
||||||
|
NeedTypesSizes,
|
||||||
|
}
|
||||||
|
|
||||||
|
var modeStrings = []string{
|
||||||
|
"NeedName",
|
||||||
|
"NeedFiles",
|
||||||
|
"NeedCompiledGoFiles",
|
||||||
|
"NeedImports",
|
||||||
|
"NeedDeps",
|
||||||
|
"NeedExportFile",
|
||||||
|
"NeedTypes",
|
||||||
|
"NeedSyntax",
|
||||||
|
"NeedTypesInfo",
|
||||||
|
"NeedTypesSizes",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mod LoadMode) String() string {
|
||||||
|
m := mod
|
||||||
|
if m == 0 {
|
||||||
|
return "LoadMode(0)"
|
||||||
|
}
|
||||||
|
var out []string
|
||||||
|
for i, x := range allModes {
|
||||||
|
if x > m {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (m & x) != 0 {
|
||||||
|
out = append(out, modeStrings[i])
|
||||||
|
m = m ^ x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if m != 0 {
|
||||||
|
out = append(out, "Unknown")
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("LoadMode(%s)", strings.Join(out, "|"))
|
||||||
|
}
|
1273
vendor/golang.org/x/tools/go/packages/packages.go
generated
vendored
Normal file
1273
vendor/golang.org/x/tools/go/packages/packages.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
59
vendor/golang.org/x/tools/go/packages/visit.go
generated
vendored
Normal file
59
vendor/golang.org/x/tools/go/packages/visit.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package packages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Visit visits all the packages in the import graph whose roots are
|
||||||
|
// pkgs, calling the optional pre function the first time each package
|
||||||
|
// is encountered (preorder), and the optional post function after a
|
||||||
|
// package's dependencies have been visited (postorder).
|
||||||
|
// The boolean result of pre(pkg) determines whether
|
||||||
|
// the imports of package pkg are visited.
|
||||||
|
func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) {
|
||||||
|
seen := make(map[*Package]bool)
|
||||||
|
var visit func(*Package)
|
||||||
|
visit = func(pkg *Package) {
|
||||||
|
if !seen[pkg] {
|
||||||
|
seen[pkg] = true
|
||||||
|
|
||||||
|
if pre == nil || pre(pkg) {
|
||||||
|
paths := make([]string, 0, len(pkg.Imports))
|
||||||
|
for path := range pkg.Imports {
|
||||||
|
paths = append(paths, path)
|
||||||
|
}
|
||||||
|
sort.Strings(paths) // Imports is a map, this makes visit stable
|
||||||
|
for _, path := range paths {
|
||||||
|
visit(pkg.Imports[path])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if post != nil {
|
||||||
|
post(pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
visit(pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintErrors prints to os.Stderr the accumulated errors of all
|
||||||
|
// packages in the import graph rooted at pkgs, dependencies first.
|
||||||
|
// PrintErrors returns the number of errors printed.
|
||||||
|
func PrintErrors(pkgs []*Package) int {
|
||||||
|
var n int
|
||||||
|
Visit(pkgs, nil, func(pkg *Package) {
|
||||||
|
for _, err := range pkg.Errors {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return n
|
||||||
|
}
|
85
vendor/golang.org/x/tools/internal/event/core/event.go
generated
vendored
Normal file
85
vendor/golang.org/x/tools/internal/event/core/event.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package core provides support for event based telemetry.
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/event/label"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Event holds the information about an event of note that occurred.
|
||||||
|
type Event struct {
|
||||||
|
at time.Time
|
||||||
|
|
||||||
|
// As events are often on the stack, storing the first few labels directly
|
||||||
|
// in the event can avoid an allocation at all for the very common cases of
|
||||||
|
// simple events.
|
||||||
|
// The length needs to be large enough to cope with the majority of events
|
||||||
|
// but no so large as to cause undue stack pressure.
|
||||||
|
// A log message with two values will use 3 labels (one for each value and
|
||||||
|
// one for the message itself).
|
||||||
|
|
||||||
|
static [3]label.Label // inline storage for the first few labels
|
||||||
|
dynamic []label.Label // dynamically sized storage for remaining labels
|
||||||
|
}
|
||||||
|
|
||||||
|
// eventLabelMap implements label.Map for a the labels of an Event.
|
||||||
|
type eventLabelMap struct {
|
||||||
|
event Event
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev Event) At() time.Time { return ev.at }
|
||||||
|
|
||||||
|
func (ev Event) Format(f fmt.State, r rune) {
|
||||||
|
if !ev.at.IsZero() {
|
||||||
|
fmt.Fprint(f, ev.at.Format("2006/01/02 15:04:05 "))
|
||||||
|
}
|
||||||
|
for index := 0; ev.Valid(index); index++ {
|
||||||
|
if l := ev.Label(index); l.Valid() {
|
||||||
|
fmt.Fprintf(f, "\n\t%v", l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev Event) Valid(index int) bool {
|
||||||
|
return index >= 0 && index < len(ev.static)+len(ev.dynamic)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev Event) Label(index int) label.Label {
|
||||||
|
if index < len(ev.static) {
|
||||||
|
return ev.static[index]
|
||||||
|
}
|
||||||
|
return ev.dynamic[index-len(ev.static)]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev Event) Find(key label.Key) label.Label {
|
||||||
|
for _, l := range ev.static {
|
||||||
|
if l.Key() == key {
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, l := range ev.dynamic {
|
||||||
|
if l.Key() == key {
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return label.Label{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeEvent(static [3]label.Label, labels []label.Label) Event {
|
||||||
|
return Event{
|
||||||
|
static: static,
|
||||||
|
dynamic: labels,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneEvent event returns a copy of the event with the time adjusted to at.
|
||||||
|
func CloneEvent(ev Event, at time.Time) Event {
|
||||||
|
ev.at = at
|
||||||
|
return ev
|
||||||
|
}
|
70
vendor/golang.org/x/tools/internal/event/core/export.go
generated
vendored
Normal file
70
vendor/golang.org/x/tools/internal/event/core/export.go
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/event/label"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Exporter is a function that handles events.
|
||||||
|
// It may return a modified context and event.
|
||||||
|
type Exporter func(context.Context, Event, label.Map) context.Context
|
||||||
|
|
||||||
|
var (
|
||||||
|
exporter unsafe.Pointer
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetExporter sets the global exporter function that handles all events.
|
||||||
|
// The exporter is called synchronously from the event call site, so it should
|
||||||
|
// return quickly so as not to hold up user code.
|
||||||
|
func SetExporter(e Exporter) {
|
||||||
|
p := unsafe.Pointer(&e)
|
||||||
|
if e == nil {
|
||||||
|
// &e is always valid, and so p is always valid, but for the early abort
|
||||||
|
// of ProcessEvent to be efficient it needs to make the nil check on the
|
||||||
|
// pointer without having to dereference it, so we make the nil function
|
||||||
|
// also a nil pointer
|
||||||
|
p = nil
|
||||||
|
}
|
||||||
|
atomic.StorePointer(&exporter, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// deliver is called to deliver an event to the supplied exporter.
|
||||||
|
// it will fill in the time.
|
||||||
|
func deliver(ctx context.Context, exporter Exporter, ev Event) context.Context {
|
||||||
|
// add the current time to the event
|
||||||
|
ev.at = time.Now()
|
||||||
|
// hand the event off to the current exporter
|
||||||
|
return exporter(ctx, ev, ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export is called to deliver an event to the global exporter if set.
|
||||||
|
func Export(ctx context.Context, ev Event) context.Context {
|
||||||
|
// get the global exporter and abort early if there is not one
|
||||||
|
exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
|
||||||
|
if exporterPtr == nil {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
return deliver(ctx, *exporterPtr, ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportPair is called to deliver a start event to the supplied exporter.
|
||||||
|
// It also returns a function that will deliver the end event to the same
|
||||||
|
// exporter.
|
||||||
|
// It will fill in the time.
|
||||||
|
func ExportPair(ctx context.Context, begin, end Event) (context.Context, func()) {
|
||||||
|
// get the global exporter and abort early if there is not one
|
||||||
|
exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
|
||||||
|
if exporterPtr == nil {
|
||||||
|
return ctx, func() {}
|
||||||
|
}
|
||||||
|
ctx = deliver(ctx, *exporterPtr, begin)
|
||||||
|
return ctx, func() { deliver(ctx, *exporterPtr, end) }
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user