mirror of
https://github.com/containerd/containerd.git
synced 2026-11-06 21:37:23 +00:00
go.mod: golang.org/x/* latest
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
224 files changed
+15404
-16261
No files matched your search
@@ -1,6 +1,6 @@
|
||||
module github.com/containerd/containerd
|
||||
|
||||
go 1.20
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0
|
||||
@@ -63,9 +63,9 @@ require (
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0
|
||||
go.opentelemetry.io/otel/sdk v1.21.0
|
||||
go.opentelemetry.io/otel/trace v1.21.0
|
||||
golang.org/x/net v0.23.0
|
||||
golang.org/x/sync v0.3.0
|
||||
golang.org/x/sys v0.18.0
|
||||
golang.org/x/net v0.42.0
|
||||
golang.org/x/sync v0.16.0
|
||||
golang.org/x/sys v0.34.0
|
||||
google.golang.org/grpc v1.59.0
|
||||
google.golang.org/protobuf v1.33.0
|
||||
k8s.io/api v0.22.5
|
||||
@@ -79,7 +79,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.3.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
|
||||
@@ -118,12 +118,11 @@ require (
|
||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.11.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/oauth2 v0.11.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
||||
@@ -13,7 +13,6 @@ cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bP
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
@@ -21,9 +20,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
|
||||
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
@@ -155,6 +153,7 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
||||
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
|
||||
@@ -347,6 +346,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
@@ -965,8 +965,8 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -1052,16 +1052,16 @@ golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
|
||||
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1075,8 +1075,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1169,8 +1169,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -1178,8 +1178,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1190,8 +1190,9 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -1199,8 +1200,9 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -1286,8 +1288,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt37+h7X16BWQbad7Q4S6gclTKFXM8=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/containerd/containerd/integration/client
|
||||
|
||||
go 1.19
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/Microsoft/hcsshim v0.9.12
|
||||
@@ -19,7 +19,7 @@ require (
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/sys v0.18.0
|
||||
golang.org/x/sys v0.34.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -47,9 +47,9 @@ require (
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/net v0.23.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
|
||||
google.golang.org/grpc v1.59.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
|
||||
@@ -65,6 +65,7 @@ cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZ
|
||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
@@ -865,9 +866,13 @@ golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -909,6 +914,11 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -986,10 +996,14 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1022,6 +1036,7 @@ golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4
|
||||
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1038,8 +1053,13 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1160,11 +1180,16 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -1180,9 +1205,12 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1203,14 +1231,19 @@ golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -1282,6 +1315,10 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
|
||||
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
Copyright 2009 The Go Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
|
||||
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
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
// Deprecated: any new system should use AES (from crypto/aes, if necessary in
|
||||
// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
|
||||
// golang.org/x/crypto/chacha20poly1305).
|
||||
package cast5 // import "golang.org/x/crypto/cast5"
|
||||
package cast5
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
+3
-2
@@ -10,14 +10,15 @@
|
||||
// for their specific task. If you are required to interoperate with OpenPGP
|
||||
// systems and need a maintained package, consider a community fork.
|
||||
// See https://golang.org/issue/44226.
|
||||
package armor // import "golang.org/x/crypto/openpgp/armor"
|
||||
package armor
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// A Block represents an OpenPGP armored structure.
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
// https://golang.org/issue/44226), and ElGamal in the OpenPGP ecosystem has
|
||||
// compatibility and security issues (see https://eprint.iacr.org/2021/923).
|
||||
// Moreover, this package doesn't protect against side-channel attacks.
|
||||
package elgamal // import "golang.org/x/crypto/openpgp/elgamal"
|
||||
package elgamal
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
// for their specific task. If you are required to interoperate with OpenPGP
|
||||
// systems and need a maintained package, consider a community fork.
|
||||
// See https://golang.org/issue/44226.
|
||||
package errors // import "golang.org/x/crypto/openpgp/errors"
|
||||
package errors
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
// for their specific task. If you are required to interoperate with OpenPGP
|
||||
// systems and need a maintained package, consider a community fork.
|
||||
// See https://golang.org/issue/44226.
|
||||
package packet // import "golang.org/x/crypto/openpgp/packet"
|
||||
package packet
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
// for their specific task. If you are required to interoperate with OpenPGP
|
||||
// systems and need a maintained package, consider a community fork.
|
||||
// See https://golang.org/issue/44226.
|
||||
package openpgp // import "golang.org/x/crypto/openpgp"
|
||||
package openpgp
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
// for their specific task. If you are required to interoperate with OpenPGP
|
||||
// systems and need a maintained package, consider a community fork.
|
||||
// See https://golang.org/issue/44226.
|
||||
package s2k // import "golang.org/x/crypto/openpgp/s2k"
|
||||
package s2k
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
|
||||
choose, you can pass the `New` functions from the different SHA packages to
|
||||
pbkdf2.Key.
|
||||
*/
|
||||
package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
|
||||
package pbkdf2
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
Copyright 2009 The Go Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
|
||||
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
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
|
||||
+100
-12
@@ -3,29 +3,31 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package context defines the Context type, which carries deadlines,
|
||||
// cancelation signals, and other request-scoped values across API boundaries
|
||||
// cancellation signals, and other request-scoped values across API boundaries
|
||||
// and between processes.
|
||||
// As of Go 1.7 this package is available in the standard library under the
|
||||
// name context. https://golang.org/pkg/context.
|
||||
// name [context], and migrating to it can be done automatically with [go fix].
|
||||
//
|
||||
// Incoming requests to a server should create a Context, and outgoing calls to
|
||||
// servers should accept a Context. The chain of function calls between must
|
||||
// propagate the Context, optionally replacing it with a modified copy created
|
||||
// using WithDeadline, WithTimeout, WithCancel, or WithValue.
|
||||
// Incoming requests to a server should create a [Context], and outgoing
|
||||
// calls to servers should accept a Context. The chain of function
|
||||
// calls between them must propagate the Context, optionally replacing
|
||||
// it with a derived Context created using [WithCancel], [WithDeadline],
|
||||
// [WithTimeout], or [WithValue].
|
||||
//
|
||||
// Programs that use Contexts should follow these rules to keep interfaces
|
||||
// consistent across packages and enable static analysis tools to check context
|
||||
// propagation:
|
||||
//
|
||||
// Do not store Contexts inside a struct type; instead, pass a Context
|
||||
// explicitly to each function that needs it. The Context should be the first
|
||||
// explicitly to each function that needs it. This is discussed further in
|
||||
// https://go.dev/blog/context-and-structs. The Context should be the first
|
||||
// parameter, typically named ctx:
|
||||
//
|
||||
// func DoSomething(ctx context.Context, arg Arg) error {
|
||||
// // ... use ctx ...
|
||||
// }
|
||||
//
|
||||
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
|
||||
// Do not pass a nil [Context], even if a function permits it. Pass [context.TODO]
|
||||
// if you are unsure about which Context to use.
|
||||
//
|
||||
// Use context Values only for request-scoped data that transits processes and
|
||||
@@ -34,9 +36,30 @@
|
||||
// The same Context may be passed to functions running in different goroutines;
|
||||
// Contexts are safe for simultaneous use by multiple goroutines.
|
||||
//
|
||||
// See http://blog.golang.org/context for example code for a server that uses
|
||||
// See https://go.dev/blog/context for example code for a server that uses
|
||||
// Contexts.
|
||||
package context // import "golang.org/x/net/context"
|
||||
//
|
||||
// [go fix]: https://go.dev/cmd/go#hdr-Update_packages_to_use_new_APIs
|
||||
package context
|
||||
|
||||
import (
|
||||
"context" // standard library's context, as of Go 1.7
|
||||
"time"
|
||||
)
|
||||
|
||||
// A Context carries a deadline, a cancellation signal, and other values across
|
||||
// API boundaries.
|
||||
//
|
||||
// Context's methods may be called by multiple goroutines simultaneously.
|
||||
type Context = context.Context
|
||||
|
||||
// Canceled is the error returned by [Context.Err] when the context is canceled
|
||||
// for some reason other than its deadline passing.
|
||||
var Canceled = context.Canceled
|
||||
|
||||
// DeadlineExceeded is the error returned by [Context.Err] when the context is canceled
|
||||
// due to its deadline passing.
|
||||
var DeadlineExceeded = context.DeadlineExceeded
|
||||
|
||||
// Background returns a non-nil, empty Context. It is never canceled, has no
|
||||
// values, and has no deadline. It is typically used by the main function,
|
||||
@@ -49,8 +72,73 @@ func Background() Context {
|
||||
// TODO returns a non-nil, empty Context. Code should use context.TODO when
|
||||
// it's unclear which Context to use or it is not yet available (because the
|
||||
// surrounding function has not yet been extended to accept a Context
|
||||
// parameter). TODO is recognized by static analysis tools that determine
|
||||
// whether Contexts are propagated correctly in a program.
|
||||
// parameter).
|
||||
func TODO() Context {
|
||||
return todo
|
||||
}
|
||||
|
||||
var (
|
||||
background = context.Background()
|
||||
todo = context.TODO()
|
||||
)
|
||||
|
||||
// A CancelFunc tells an operation to abandon its work.
|
||||
// A CancelFunc does not wait for the work to stop.
|
||||
// A CancelFunc may be called by multiple goroutines simultaneously.
|
||||
// After the first call, subsequent calls to a CancelFunc do nothing.
|
||||
type CancelFunc = context.CancelFunc
|
||||
|
||||
// WithCancel returns a derived context that points to the parent context
|
||||
// but has a new Done channel. The returned context's Done channel is closed
|
||||
// when the returned cancel function is called or when the parent context's
|
||||
// Done channel is closed, whichever happens first.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this [Context] complete.
|
||||
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
||||
return context.WithCancel(parent)
|
||||
}
|
||||
|
||||
// WithDeadline returns a derived context that points to the parent context
|
||||
// but has the deadline adjusted to be no later than d. If the parent's
|
||||
// deadline is already earlier than d, WithDeadline(parent, d) is semantically
|
||||
// equivalent to parent. The returned [Context.Done] channel is closed when
|
||||
// the deadline expires, when the returned cancel function is called,
|
||||
// or when the parent context's Done channel is closed, whichever happens first.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this [Context] complete.
|
||||
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
|
||||
return context.WithDeadline(parent, d)
|
||||
}
|
||||
|
||||
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this [Context] complete:
|
||||
//
|
||||
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
|
||||
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
||||
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
||||
// return slowOperation(ctx)
|
||||
// }
|
||||
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
||||
return context.WithTimeout(parent, timeout)
|
||||
}
|
||||
|
||||
// WithValue returns a derived context that points to the parent Context.
|
||||
// In the derived context, the value associated with key is val.
|
||||
//
|
||||
// Use context Values only for request-scoped data that transits processes and
|
||||
// APIs, not for passing optional parameters to functions.
|
||||
//
|
||||
// The provided key must be comparable and should not be of type
|
||||
// string or any other built-in type to avoid collisions between
|
||||
// packages using context. Users of WithValue should define their own
|
||||
// types for keys. To avoid allocating when assigning to an
|
||||
// interface{}, context keys often have concrete type
|
||||
// struct{}. Alternatively, exported context key variables' static
|
||||
// type should be a pointer or interface.
|
||||
func WithValue(parent Context, key, val interface{}) Context {
|
||||
return context.WithValue(parent, key, val)
|
||||
}
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
|
||||
package ctxhttp // import "golang.org/x/net/context/ctxhttp"
|
||||
package ctxhttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
// 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.
|
||||
|
||||
//go:build go1.7
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
"context" // standard library's context, as of Go 1.7
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
todo = context.TODO()
|
||||
background = context.Background()
|
||||
)
|
||||
|
||||
// Canceled is the error returned by Context.Err when the context is canceled.
|
||||
var Canceled = context.Canceled
|
||||
|
||||
// DeadlineExceeded is the error returned by Context.Err when the context's
|
||||
// deadline passes.
|
||||
var DeadlineExceeded = context.DeadlineExceeded
|
||||
|
||||
// WithCancel returns a copy of parent with a new Done channel. The returned
|
||||
// context's Done channel is closed when the returned cancel function is called
|
||||
// or when the parent context's Done channel is closed, whichever happens first.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
||||
ctx, f := context.WithCancel(parent)
|
||||
return ctx, f
|
||||
}
|
||||
|
||||
// WithDeadline returns a copy of the parent context with the deadline adjusted
|
||||
// to be no later than d. If the parent's deadline is already earlier than d,
|
||||
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
||||
// context's Done channel is closed when the deadline expires, when the returned
|
||||
// cancel function is called, or when the parent context's Done channel is
|
||||
// closed, whichever happens first.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
|
||||
ctx, f := context.WithDeadline(parent, deadline)
|
||||
return ctx, f
|
||||
}
|
||||
|
||||
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete:
|
||||
//
|
||||
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
|
||||
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
||||
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
||||
// return slowOperation(ctx)
|
||||
// }
|
||||
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
||||
return WithDeadline(parent, time.Now().Add(timeout))
|
||||
}
|
||||
|
||||
// WithValue returns a copy of parent in which the value associated with key is
|
||||
// val.
|
||||
//
|
||||
// Use context Values only for request-scoped data that transits processes and
|
||||
// APIs, not for passing optional parameters to functions.
|
||||
func WithValue(parent Context, key interface{}, val interface{}) Context {
|
||||
return context.WithValue(parent, key, val)
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
// Copyright 2017 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.9
|
||||
|
||||
package context
|
||||
|
||||
import "context" // standard library's context, as of Go 1.7
|
||||
|
||||
// A Context carries a deadline, a cancelation signal, and other values across
|
||||
// API boundaries.
|
||||
//
|
||||
// Context's methods may be called by multiple goroutines simultaneously.
|
||||
type Context = context.Context
|
||||
|
||||
// A CancelFunc tells an operation to abandon its work.
|
||||
// A CancelFunc does not wait for the work to stop.
|
||||
// After the first call, subsequent calls to a CancelFunc do nothing.
|
||||
type CancelFunc = context.CancelFunc
|
||||
-300
@@ -1,300 +0,0 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.7
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
|
||||
// struct{}, since vars of this type must have distinct addresses.
|
||||
type emptyCtx int
|
||||
|
||||
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (*emptyCtx) Done() <-chan struct{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*emptyCtx) Err() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*emptyCtx) Value(key interface{}) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *emptyCtx) String() string {
|
||||
switch e {
|
||||
case background:
|
||||
return "context.Background"
|
||||
case todo:
|
||||
return "context.TODO"
|
||||
}
|
||||
return "unknown empty Context"
|
||||
}
|
||||
|
||||
var (
|
||||
background = new(emptyCtx)
|
||||
todo = new(emptyCtx)
|
||||
)
|
||||
|
||||
// Canceled is the error returned by Context.Err when the context is canceled.
|
||||
var Canceled = errors.New("context canceled")
|
||||
|
||||
// DeadlineExceeded is the error returned by Context.Err when the context's
|
||||
// deadline passes.
|
||||
var DeadlineExceeded = errors.New("context deadline exceeded")
|
||||
|
||||
// WithCancel returns a copy of parent with a new Done channel. The returned
|
||||
// context's Done channel is closed when the returned cancel function is called
|
||||
// or when the parent context's Done channel is closed, whichever happens first.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
||||
c := newCancelCtx(parent)
|
||||
propagateCancel(parent, c)
|
||||
return c, func() { c.cancel(true, Canceled) }
|
||||
}
|
||||
|
||||
// newCancelCtx returns an initialized cancelCtx.
|
||||
func newCancelCtx(parent Context) *cancelCtx {
|
||||
return &cancelCtx{
|
||||
Context: parent,
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// propagateCancel arranges for child to be canceled when parent is.
|
||||
func propagateCancel(parent Context, child canceler) {
|
||||
if parent.Done() == nil {
|
||||
return // parent is never canceled
|
||||
}
|
||||
if p, ok := parentCancelCtx(parent); ok {
|
||||
p.mu.Lock()
|
||||
if p.err != nil {
|
||||
// parent has already been canceled
|
||||
child.cancel(false, p.err)
|
||||
} else {
|
||||
if p.children == nil {
|
||||
p.children = make(map[canceler]bool)
|
||||
}
|
||||
p.children[child] = true
|
||||
}
|
||||
p.mu.Unlock()
|
||||
} else {
|
||||
go func() {
|
||||
select {
|
||||
case <-parent.Done():
|
||||
child.cancel(false, parent.Err())
|
||||
case <-child.Done():
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// parentCancelCtx follows a chain of parent references until it finds a
|
||||
// *cancelCtx. This function understands how each of the concrete types in this
|
||||
// package represents its parent.
|
||||
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
|
||||
for {
|
||||
switch c := parent.(type) {
|
||||
case *cancelCtx:
|
||||
return c, true
|
||||
case *timerCtx:
|
||||
return c.cancelCtx, true
|
||||
case *valueCtx:
|
||||
parent = c.Context
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// removeChild removes a context from its parent.
|
||||
func removeChild(parent Context, child canceler) {
|
||||
p, ok := parentCancelCtx(parent)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
p.mu.Lock()
|
||||
if p.children != nil {
|
||||
delete(p.children, child)
|
||||
}
|
||||
p.mu.Unlock()
|
||||
}
|
||||
|
||||
// A canceler is a context type that can be canceled directly. The
|
||||
// implementations are *cancelCtx and *timerCtx.
|
||||
type canceler interface {
|
||||
cancel(removeFromParent bool, err error)
|
||||
Done() <-chan struct{}
|
||||
}
|
||||
|
||||
// A cancelCtx can be canceled. When canceled, it also cancels any children
|
||||
// that implement canceler.
|
||||
type cancelCtx struct {
|
||||
Context
|
||||
|
||||
done chan struct{} // closed by the first cancel call.
|
||||
|
||||
mu sync.Mutex
|
||||
children map[canceler]bool // set to nil by the first cancel call
|
||||
err error // set to non-nil by the first cancel call
|
||||
}
|
||||
|
||||
func (c *cancelCtx) Done() <-chan struct{} {
|
||||
return c.done
|
||||
}
|
||||
|
||||
func (c *cancelCtx) Err() error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.err
|
||||
}
|
||||
|
||||
func (c *cancelCtx) String() string {
|
||||
return fmt.Sprintf("%v.WithCancel", c.Context)
|
||||
}
|
||||
|
||||
// cancel closes c.done, cancels each of c's children, and, if
|
||||
// removeFromParent is true, removes c from its parent's children.
|
||||
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
|
||||
if err == nil {
|
||||
panic("context: internal error: missing cancel error")
|
||||
}
|
||||
c.mu.Lock()
|
||||
if c.err != nil {
|
||||
c.mu.Unlock()
|
||||
return // already canceled
|
||||
}
|
||||
c.err = err
|
||||
close(c.done)
|
||||
for child := range c.children {
|
||||
// NOTE: acquiring the child's lock while holding parent's lock.
|
||||
child.cancel(false, err)
|
||||
}
|
||||
c.children = nil
|
||||
c.mu.Unlock()
|
||||
|
||||
if removeFromParent {
|
||||
removeChild(c.Context, c)
|
||||
}
|
||||
}
|
||||
|
||||
// WithDeadline returns a copy of the parent context with the deadline adjusted
|
||||
// to be no later than d. If the parent's deadline is already earlier than d,
|
||||
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
||||
// context's Done channel is closed when the deadline expires, when the returned
|
||||
// cancel function is called, or when the parent context's Done channel is
|
||||
// closed, whichever happens first.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
|
||||
if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
|
||||
// The current deadline is already sooner than the new one.
|
||||
return WithCancel(parent)
|
||||
}
|
||||
c := &timerCtx{
|
||||
cancelCtx: newCancelCtx(parent),
|
||||
deadline: deadline,
|
||||
}
|
||||
propagateCancel(parent, c)
|
||||
d := deadline.Sub(time.Now())
|
||||
if d <= 0 {
|
||||
c.cancel(true, DeadlineExceeded) // deadline has already passed
|
||||
return c, func() { c.cancel(true, Canceled) }
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.err == nil {
|
||||
c.timer = time.AfterFunc(d, func() {
|
||||
c.cancel(true, DeadlineExceeded)
|
||||
})
|
||||
}
|
||||
return c, func() { c.cancel(true, Canceled) }
|
||||
}
|
||||
|
||||
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
|
||||
// implement Done and Err. It implements cancel by stopping its timer then
|
||||
// delegating to cancelCtx.cancel.
|
||||
type timerCtx struct {
|
||||
*cancelCtx
|
||||
timer *time.Timer // Under cancelCtx.mu.
|
||||
|
||||
deadline time.Time
|
||||
}
|
||||
|
||||
func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
|
||||
return c.deadline, true
|
||||
}
|
||||
|
||||
func (c *timerCtx) String() string {
|
||||
return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
|
||||
}
|
||||
|
||||
func (c *timerCtx) cancel(removeFromParent bool, err error) {
|
||||
c.cancelCtx.cancel(false, err)
|
||||
if removeFromParent {
|
||||
// Remove this timerCtx from its parent cancelCtx's children.
|
||||
removeChild(c.cancelCtx.Context, c)
|
||||
}
|
||||
c.mu.Lock()
|
||||
if c.timer != nil {
|
||||
c.timer.Stop()
|
||||
c.timer = nil
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete:
|
||||
//
|
||||
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
|
||||
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
||||
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
||||
// return slowOperation(ctx)
|
||||
// }
|
||||
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
||||
return WithDeadline(parent, time.Now().Add(timeout))
|
||||
}
|
||||
|
||||
// WithValue returns a copy of parent in which the value associated with key is
|
||||
// val.
|
||||
//
|
||||
// Use context Values only for request-scoped data that transits processes and
|
||||
// APIs, not for passing optional parameters to functions.
|
||||
func WithValue(parent Context, key interface{}, val interface{}) Context {
|
||||
return &valueCtx{parent, key, val}
|
||||
}
|
||||
|
||||
// A valueCtx carries a key-value pair. It implements Value for that key and
|
||||
// delegates all other calls to the embedded Context.
|
||||
type valueCtx struct {
|
||||
Context
|
||||
key, val interface{}
|
||||
}
|
||||
|
||||
func (c *valueCtx) String() string {
|
||||
return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
|
||||
}
|
||||
|
||||
func (c *valueCtx) Value(key interface{}) interface{} {
|
||||
if c.key == key {
|
||||
return c.val
|
||||
}
|
||||
return c.Context.Value(key)
|
||||
}
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.9
|
||||
|
||||
package context
|
||||
|
||||
import "time"
|
||||
|
||||
// A Context carries a deadline, a cancelation signal, and other values across
|
||||
// API boundaries.
|
||||
//
|
||||
// Context's methods may be called by multiple goroutines simultaneously.
|
||||
type Context interface {
|
||||
// Deadline returns the time when work done on behalf of this context
|
||||
// should be canceled. Deadline returns ok==false when no deadline is
|
||||
// set. Successive calls to Deadline return the same results.
|
||||
Deadline() (deadline time.Time, ok bool)
|
||||
|
||||
// Done returns a channel that's closed when work done on behalf of this
|
||||
// context should be canceled. Done may return nil if this context can
|
||||
// never be canceled. Successive calls to Done return the same value.
|
||||
//
|
||||
// WithCancel arranges for Done to be closed when cancel is called;
|
||||
// WithDeadline arranges for Done to be closed when the deadline
|
||||
// expires; WithTimeout arranges for Done to be closed when the timeout
|
||||
// elapses.
|
||||
//
|
||||
// Done is provided for use in select statements:
|
||||
//
|
||||
// // Stream generates values with DoSomething and sends them to out
|
||||
// // until DoSomething returns an error or ctx.Done is closed.
|
||||
// func Stream(ctx context.Context, out chan<- Value) error {
|
||||
// for {
|
||||
// v, err := DoSomething(ctx)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// select {
|
||||
// case <-ctx.Done():
|
||||
// return ctx.Err()
|
||||
// case out <- v:
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// See http://blog.golang.org/pipelines for more examples of how to use
|
||||
// a Done channel for cancelation.
|
||||
Done() <-chan struct{}
|
||||
|
||||
// Err returns a non-nil error value after Done is closed. Err returns
|
||||
// Canceled if the context was canceled or DeadlineExceeded if the
|
||||
// context's deadline passed. No other values for Err are defined.
|
||||
// After Done is closed, successive calls to Err return the same value.
|
||||
Err() error
|
||||
|
||||
// Value returns the value associated with this context for key, or nil
|
||||
// if no value is associated with key. Successive calls to Value with
|
||||
// the same key returns the same result.
|
||||
//
|
||||
// Use context values only for request-scoped data that transits
|
||||
// processes and API boundaries, not for passing optional parameters to
|
||||
// functions.
|
||||
//
|
||||
// A key identifies a specific value in a Context. Functions that wish
|
||||
// to store values in Context typically allocate a key in a global
|
||||
// variable then use that key as the argument to context.WithValue and
|
||||
// Context.Value. A key can be any type that supports equality;
|
||||
// packages should define keys as an unexported type to avoid
|
||||
// collisions.
|
||||
//
|
||||
// Packages that define a Context key should provide type-safe accessors
|
||||
// for the values stores using that key:
|
||||
//
|
||||
// // Package user defines a User type that's stored in Contexts.
|
||||
// package user
|
||||
//
|
||||
// import "golang.org/x/net/context"
|
||||
//
|
||||
// // User is the type of value stored in the Contexts.
|
||||
// type User struct {...}
|
||||
//
|
||||
// // key is an unexported type for keys defined in this package.
|
||||
// // This prevents collisions with keys defined in other packages.
|
||||
// type key int
|
||||
//
|
||||
// // userKey is the key for user.User values in Contexts. It is
|
||||
// // unexported; clients use user.NewContext and user.FromContext
|
||||
// // instead of using this key directly.
|
||||
// var userKey key = 0
|
||||
//
|
||||
// // NewContext returns a new Context that carries value u.
|
||||
// func NewContext(ctx context.Context, u *User) context.Context {
|
||||
// return context.WithValue(ctx, userKey, u)
|
||||
// }
|
||||
//
|
||||
// // FromContext returns the User value stored in ctx, if any.
|
||||
// func FromContext(ctx context.Context) (*User, bool) {
|
||||
// u, ok := ctx.Value(userKey).(*User)
|
||||
// return u, ok
|
||||
// }
|
||||
Value(key interface{}) interface{}
|
||||
}
|
||||
|
||||
// A CancelFunc tells an operation to abandon its work.
|
||||
// A CancelFunc does not wait for the work to stop.
|
||||
// After the first call, subsequent calls to a CancelFunc do nothing.
|
||||
type CancelFunc func()
|
||||
+4
-9
@@ -12,7 +12,7 @@ import (
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
var isTokenTable = [127]bool{
|
||||
var isTokenTable = [256]bool{
|
||||
'!': true,
|
||||
'#': true,
|
||||
'$': true,
|
||||
@@ -93,12 +93,7 @@ var isTokenTable = [127]bool{
|
||||
}
|
||||
|
||||
func IsTokenRune(r rune) bool {
|
||||
i := int(r)
|
||||
return i < len(isTokenTable) && isTokenTable[i]
|
||||
}
|
||||
|
||||
func isNotToken(r rune) bool {
|
||||
return !IsTokenRune(r)
|
||||
return r < utf8.RuneSelf && isTokenTable[byte(r)]
|
||||
}
|
||||
|
||||
// HeaderValuesContainsToken reports whether any string in values
|
||||
@@ -202,8 +197,8 @@ func ValidHeaderFieldName(v string) bool {
|
||||
if len(v) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, r := range v {
|
||||
if !IsTokenRune(r) {
|
||||
for i := 0; i < len(v); i++ {
|
||||
if !isTokenTable[v[i]] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -8,8 +8,8 @@ package http2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
@@ -158,7 +158,7 @@ func (c *dialCall) dial(ctx context.Context, addr string) {
|
||||
// This code decides which ones live or die.
|
||||
// The return value used is whether c was used.
|
||||
// c is never closed.
|
||||
func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn) (used bool, err error) {
|
||||
func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c net.Conn) (used bool, err error) {
|
||||
p.mu.Lock()
|
||||
for _, cc := range p.conns[key] {
|
||||
if cc.CanTakeNewRequest() {
|
||||
@@ -194,8 +194,8 @@ type addConnCall struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
|
||||
cc, err := t.NewClientConn(tc)
|
||||
func (c *addConnCall) run(t *Transport, key string, nc net.Conn) {
|
||||
cc, err := t.NewClientConn(nc)
|
||||
|
||||
p := c.p
|
||||
p.mu.Lock()
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
// Copyright 2024 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 http2
|
||||
|
||||
import (
|
||||
"math"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// http2Config is a package-internal version of net/http.HTTP2Config.
|
||||
//
|
||||
// http.HTTP2Config was added in Go 1.24.
|
||||
// When running with a version of net/http that includes HTTP2Config,
|
||||
// we merge the configuration with the fields in Transport or Server
|
||||
// to produce an http2Config.
|
||||
//
|
||||
// Zero valued fields in http2Config are interpreted as in the
|
||||
// net/http.HTTPConfig documentation.
|
||||
//
|
||||
// Precedence order for reconciling configurations is:
|
||||
//
|
||||
// - Use the net/http.{Server,Transport}.HTTP2Config value, when non-zero.
|
||||
// - Otherwise use the http2.{Server.Transport} value.
|
||||
// - If the resulting value is zero or out of range, use a default.
|
||||
type http2Config struct {
|
||||
MaxConcurrentStreams uint32
|
||||
MaxDecoderHeaderTableSize uint32
|
||||
MaxEncoderHeaderTableSize uint32
|
||||
MaxReadFrameSize uint32
|
||||
MaxUploadBufferPerConnection int32
|
||||
MaxUploadBufferPerStream int32
|
||||
SendPingTimeout time.Duration
|
||||
PingTimeout time.Duration
|
||||
WriteByteTimeout time.Duration
|
||||
PermitProhibitedCipherSuites bool
|
||||
CountError func(errType string)
|
||||
}
|
||||
|
||||
// configFromServer merges configuration settings from
|
||||
// net/http.Server.HTTP2Config and http2.Server.
|
||||
func configFromServer(h1 *http.Server, h2 *Server) http2Config {
|
||||
conf := http2Config{
|
||||
MaxConcurrentStreams: h2.MaxConcurrentStreams,
|
||||
MaxEncoderHeaderTableSize: h2.MaxEncoderHeaderTableSize,
|
||||
MaxDecoderHeaderTableSize: h2.MaxDecoderHeaderTableSize,
|
||||
MaxReadFrameSize: h2.MaxReadFrameSize,
|
||||
MaxUploadBufferPerConnection: h2.MaxUploadBufferPerConnection,
|
||||
MaxUploadBufferPerStream: h2.MaxUploadBufferPerStream,
|
||||
SendPingTimeout: h2.ReadIdleTimeout,
|
||||
PingTimeout: h2.PingTimeout,
|
||||
WriteByteTimeout: h2.WriteByteTimeout,
|
||||
PermitProhibitedCipherSuites: h2.PermitProhibitedCipherSuites,
|
||||
CountError: h2.CountError,
|
||||
}
|
||||
fillNetHTTPServerConfig(&conf, h1)
|
||||
setConfigDefaults(&conf, true)
|
||||
return conf
|
||||
}
|
||||
|
||||
// configFromTransport merges configuration settings from h2 and h2.t1.HTTP2
|
||||
// (the net/http Transport).
|
||||
func configFromTransport(h2 *Transport) http2Config {
|
||||
conf := http2Config{
|
||||
MaxEncoderHeaderTableSize: h2.MaxEncoderHeaderTableSize,
|
||||
MaxDecoderHeaderTableSize: h2.MaxDecoderHeaderTableSize,
|
||||
MaxReadFrameSize: h2.MaxReadFrameSize,
|
||||
SendPingTimeout: h2.ReadIdleTimeout,
|
||||
PingTimeout: h2.PingTimeout,
|
||||
WriteByteTimeout: h2.WriteByteTimeout,
|
||||
}
|
||||
|
||||
// Unlike most config fields, where out-of-range values revert to the default,
|
||||
// Transport.MaxReadFrameSize clips.
|
||||
if conf.MaxReadFrameSize < minMaxFrameSize {
|
||||
conf.MaxReadFrameSize = minMaxFrameSize
|
||||
} else if conf.MaxReadFrameSize > maxFrameSize {
|
||||
conf.MaxReadFrameSize = maxFrameSize
|
||||
}
|
||||
|
||||
if h2.t1 != nil {
|
||||
fillNetHTTPTransportConfig(&conf, h2.t1)
|
||||
}
|
||||
setConfigDefaults(&conf, false)
|
||||
return conf
|
||||
}
|
||||
|
||||
func setDefault[T ~int | ~int32 | ~uint32 | ~int64](v *T, minval, maxval, defval T) {
|
||||
if *v < minval || *v > maxval {
|
||||
*v = defval
|
||||
}
|
||||
}
|
||||
|
||||
func setConfigDefaults(conf *http2Config, server bool) {
|
||||
setDefault(&conf.MaxConcurrentStreams, 1, math.MaxUint32, defaultMaxStreams)
|
||||
setDefault(&conf.MaxEncoderHeaderTableSize, 1, math.MaxUint32, initialHeaderTableSize)
|
||||
setDefault(&conf.MaxDecoderHeaderTableSize, 1, math.MaxUint32, initialHeaderTableSize)
|
||||
if server {
|
||||
setDefault(&conf.MaxUploadBufferPerConnection, initialWindowSize, math.MaxInt32, 1<<20)
|
||||
} else {
|
||||
setDefault(&conf.MaxUploadBufferPerConnection, initialWindowSize, math.MaxInt32, transportDefaultConnFlow)
|
||||
}
|
||||
if server {
|
||||
setDefault(&conf.MaxUploadBufferPerStream, 1, math.MaxInt32, 1<<20)
|
||||
} else {
|
||||
setDefault(&conf.MaxUploadBufferPerStream, 1, math.MaxInt32, transportDefaultStreamFlow)
|
||||
}
|
||||
setDefault(&conf.MaxReadFrameSize, minMaxFrameSize, maxFrameSize, defaultMaxReadFrameSize)
|
||||
setDefault(&conf.PingTimeout, 1, math.MaxInt64, 15*time.Second)
|
||||
}
|
||||
|
||||
// adjustHTTP1MaxHeaderSize converts a limit in bytes on the size of an HTTP/1 header
|
||||
// to an HTTP/2 MAX_HEADER_LIST_SIZE value.
|
||||
func adjustHTTP1MaxHeaderSize(n int64) int64 {
|
||||
// http2's count is in a slightly different unit and includes 32 bytes per pair.
|
||||
// So, take the net/http.Server value and pad it up a bit, assuming 10 headers.
|
||||
const perFieldOverhead = 32 // per http2 spec
|
||||
const typicalHeaders = 10 // conservative
|
||||
return n + typicalHeaders*perFieldOverhead
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// Copyright 2024 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.24
|
||||
|
||||
package http2
|
||||
|
||||
import "net/http"
|
||||
|
||||
// fillNetHTTPServerConfig sets fields in conf from srv.HTTP2.
|
||||
func fillNetHTTPServerConfig(conf *http2Config, srv *http.Server) {
|
||||
fillNetHTTPConfig(conf, srv.HTTP2)
|
||||
}
|
||||
|
||||
// fillNetHTTPTransportConfig sets fields in conf from tr.HTTP2.
|
||||
func fillNetHTTPTransportConfig(conf *http2Config, tr *http.Transport) {
|
||||
fillNetHTTPConfig(conf, tr.HTTP2)
|
||||
}
|
||||
|
||||
func fillNetHTTPConfig(conf *http2Config, h2 *http.HTTP2Config) {
|
||||
if h2 == nil {
|
||||
return
|
||||
}
|
||||
if h2.MaxConcurrentStreams != 0 {
|
||||
conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
|
||||
}
|
||||
if h2.MaxEncoderHeaderTableSize != 0 {
|
||||
conf.MaxEncoderHeaderTableSize = uint32(h2.MaxEncoderHeaderTableSize)
|
||||
}
|
||||
if h2.MaxDecoderHeaderTableSize != 0 {
|
||||
conf.MaxDecoderHeaderTableSize = uint32(h2.MaxDecoderHeaderTableSize)
|
||||
}
|
||||
if h2.MaxConcurrentStreams != 0 {
|
||||
conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
|
||||
}
|
||||
if h2.MaxReadFrameSize != 0 {
|
||||
conf.MaxReadFrameSize = uint32(h2.MaxReadFrameSize)
|
||||
}
|
||||
if h2.MaxReceiveBufferPerConnection != 0 {
|
||||
conf.MaxUploadBufferPerConnection = int32(h2.MaxReceiveBufferPerConnection)
|
||||
}
|
||||
if h2.MaxReceiveBufferPerStream != 0 {
|
||||
conf.MaxUploadBufferPerStream = int32(h2.MaxReceiveBufferPerStream)
|
||||
}
|
||||
if h2.SendPingTimeout != 0 {
|
||||
conf.SendPingTimeout = h2.SendPingTimeout
|
||||
}
|
||||
if h2.PingTimeout != 0 {
|
||||
conf.PingTimeout = h2.PingTimeout
|
||||
}
|
||||
if h2.WriteByteTimeout != 0 {
|
||||
conf.WriteByteTimeout = h2.WriteByteTimeout
|
||||
}
|
||||
if h2.PermitProhibitedCipherSuites {
|
||||
conf.PermitProhibitedCipherSuites = true
|
||||
}
|
||||
if h2.CountError != nil {
|
||||
conf.CountError = h2.CountError
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// Copyright 2024 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.24
|
||||
|
||||
package http2
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Pre-Go 1.24 fallback.
|
||||
// The Server.HTTP2 and Transport.HTTP2 config fields were added in Go 1.24.
|
||||
|
||||
func fillNetHTTPServerConfig(conf *http2Config, srv *http.Server) {}
|
||||
|
||||
func fillNetHTTPTransportConfig(conf *http2Config, tr *http.Transport) {}
|
||||
+28
-14
@@ -39,7 +39,7 @@ const (
|
||||
FrameContinuation FrameType = 0x9
|
||||
)
|
||||
|
||||
var frameName = map[FrameType]string{
|
||||
var frameNames = [...]string{
|
||||
FrameData: "DATA",
|
||||
FrameHeaders: "HEADERS",
|
||||
FramePriority: "PRIORITY",
|
||||
@@ -53,10 +53,10 @@ var frameName = map[FrameType]string{
|
||||
}
|
||||
|
||||
func (t FrameType) String() string {
|
||||
if s, ok := frameName[t]; ok {
|
||||
return s
|
||||
if int(t) < len(frameNames) {
|
||||
return frameNames[t]
|
||||
}
|
||||
return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t))
|
||||
return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", t)
|
||||
}
|
||||
|
||||
// Flags is a bitmask of HTTP/2 flags.
|
||||
@@ -124,7 +124,7 @@ var flagName = map[FrameType]map[Flags]string{
|
||||
// might be 0).
|
||||
type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error)
|
||||
|
||||
var frameParsers = map[FrameType]frameParser{
|
||||
var frameParsers = [...]frameParser{
|
||||
FrameData: parseDataFrame,
|
||||
FrameHeaders: parseHeadersFrame,
|
||||
FramePriority: parsePriorityFrame,
|
||||
@@ -138,8 +138,8 @@ var frameParsers = map[FrameType]frameParser{
|
||||
}
|
||||
|
||||
func typeFrameParser(t FrameType) frameParser {
|
||||
if f := frameParsers[t]; f != nil {
|
||||
return f
|
||||
if int(t) < len(frameParsers) {
|
||||
return frameParsers[t]
|
||||
}
|
||||
return parseUnknownFrame
|
||||
}
|
||||
@@ -225,6 +225,11 @@ var fhBytes = sync.Pool{
|
||||
},
|
||||
}
|
||||
|
||||
func invalidHTTP1LookingFrameHeader() FrameHeader {
|
||||
fh, _ := readFrameHeader(make([]byte, frameHeaderLen), strings.NewReader("HTTP/1.1 "))
|
||||
return fh
|
||||
}
|
||||
|
||||
// ReadFrameHeader reads 9 bytes from r and returns a FrameHeader.
|
||||
// Most users should use Framer.ReadFrame instead.
|
||||
func ReadFrameHeader(r io.Reader) (FrameHeader, error) {
|
||||
@@ -490,6 +495,9 @@ func terminalReadFrameError(err error) bool {
|
||||
// returned error is ErrFrameTooLarge. Other errors may be of type
|
||||
// ConnectionError, StreamError, or anything else from the underlying
|
||||
// reader.
|
||||
//
|
||||
// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
|
||||
// indicates the stream responsible for the error.
|
||||
func (fr *Framer) ReadFrame() (Frame, error) {
|
||||
fr.errDetail = nil
|
||||
if fr.lastFrame != nil {
|
||||
@@ -500,10 +508,16 @@ func (fr *Framer) ReadFrame() (Frame, error) {
|
||||
return nil, err
|
||||
}
|
||||
if fh.Length > fr.maxReadSize {
|
||||
if fh == invalidHTTP1LookingFrameHeader() {
|
||||
return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge)
|
||||
}
|
||||
return nil, ErrFrameTooLarge
|
||||
}
|
||||
payload := fr.getReadBuf(fh.Length)
|
||||
if _, err := io.ReadFull(fr.r, payload); err != nil {
|
||||
if fh == invalidHTTP1LookingFrameHeader() {
|
||||
return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, fr.countError, payload)
|
||||
@@ -1487,7 +1501,7 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
|
||||
pf := mh.PseudoFields()
|
||||
for i, hf := range pf {
|
||||
switch hf.Name {
|
||||
case ":method", ":path", ":scheme", ":authority":
|
||||
case ":method", ":path", ":scheme", ":authority", ":protocol":
|
||||
isRequest = true
|
||||
case ":status":
|
||||
isResponse = true
|
||||
@@ -1495,7 +1509,7 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
|
||||
return pseudoHeaderError(hf.Name)
|
||||
}
|
||||
// Check for duplicates.
|
||||
// This would be a bad algorithm, but N is 4.
|
||||
// This would be a bad algorithm, but N is 5.
|
||||
// And this doesn't allocate.
|
||||
for _, hf2 := range pf[:i] {
|
||||
if hf.Name == hf2.Name {
|
||||
@@ -1521,7 +1535,7 @@ func (fr *Framer) maxHeaderStringLen() int {
|
||||
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
|
||||
// merge them into the provided hf and returns a MetaHeadersFrame
|
||||
// with the decoded hpack values.
|
||||
func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
||||
func (fr *Framer) readMetaFrame(hf *HeadersFrame) (Frame, error) {
|
||||
if fr.AllowIllegalReads {
|
||||
return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders")
|
||||
}
|
||||
@@ -1592,7 +1606,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
||||
}
|
||||
// It would be nice to send a RST_STREAM before sending the GOAWAY,
|
||||
// but the structure of the server's frame writer makes this difficult.
|
||||
return nil, ConnectionError(ErrCodeProtocol)
|
||||
return mh, ConnectionError(ErrCodeProtocol)
|
||||
}
|
||||
|
||||
// Also close the connection after any CONTINUATION frame following an
|
||||
@@ -1604,11 +1618,11 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
||||
}
|
||||
// It would be nice to send a RST_STREAM before sending the GOAWAY,
|
||||
// but the structure of the server's frame writer makes this difficult.
|
||||
return nil, ConnectionError(ErrCodeProtocol)
|
||||
return mh, ConnectionError(ErrCodeProtocol)
|
||||
}
|
||||
|
||||
if _, err := hdec.Write(frag); err != nil {
|
||||
return nil, ConnectionError(ErrCodeCompression)
|
||||
return mh, ConnectionError(ErrCodeCompression)
|
||||
}
|
||||
|
||||
if hc.HeadersEnded() {
|
||||
@@ -1625,7 +1639,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
||||
mh.HeadersFrame.invalidate()
|
||||
|
||||
if err := hdec.Close(); err != nil {
|
||||
return nil, ConnectionError(ErrCodeCompression)
|
||||
return mh, ConnectionError(ErrCodeCompression)
|
||||
}
|
||||
if invalid != nil {
|
||||
fr.errDetail = invalid
|
||||
|
||||
+89
-42
@@ -17,15 +17,18 @@ package http2 // import "golang.org/x/net/http2"
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http/httpguts"
|
||||
)
|
||||
@@ -35,6 +38,15 @@ var (
|
||||
logFrameWrites bool
|
||||
logFrameReads bool
|
||||
inTests bool
|
||||
|
||||
// Enabling extended CONNECT by causes browsers to attempt to use
|
||||
// WebSockets-over-HTTP/2. This results in problems when the server's websocket
|
||||
// package doesn't support extended CONNECT.
|
||||
//
|
||||
// Disable extended CONNECT by default for now.
|
||||
//
|
||||
// Issue #71128.
|
||||
disableExtendedConnectProtocol = true
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -47,6 +59,9 @@ func init() {
|
||||
logFrameWrites = true
|
||||
logFrameReads = true
|
||||
}
|
||||
if strings.Contains(e, "http2xconnect=1") {
|
||||
disableExtendedConnectProtocol = false
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -138,6 +153,10 @@ func (s Setting) Valid() error {
|
||||
if s.Val < 16384 || s.Val > 1<<24-1 {
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
}
|
||||
case SettingEnableConnectProtocol:
|
||||
if s.Val != 1 && s.Val != 0 {
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -147,21 +166,23 @@ func (s Setting) Valid() error {
|
||||
type SettingID uint16
|
||||
|
||||
const (
|
||||
SettingHeaderTableSize SettingID = 0x1
|
||||
SettingEnablePush SettingID = 0x2
|
||||
SettingMaxConcurrentStreams SettingID = 0x3
|
||||
SettingInitialWindowSize SettingID = 0x4
|
||||
SettingMaxFrameSize SettingID = 0x5
|
||||
SettingMaxHeaderListSize SettingID = 0x6
|
||||
SettingHeaderTableSize SettingID = 0x1
|
||||
SettingEnablePush SettingID = 0x2
|
||||
SettingMaxConcurrentStreams SettingID = 0x3
|
||||
SettingInitialWindowSize SettingID = 0x4
|
||||
SettingMaxFrameSize SettingID = 0x5
|
||||
SettingMaxHeaderListSize SettingID = 0x6
|
||||
SettingEnableConnectProtocol SettingID = 0x8
|
||||
)
|
||||
|
||||
var settingName = map[SettingID]string{
|
||||
SettingHeaderTableSize: "HEADER_TABLE_SIZE",
|
||||
SettingEnablePush: "ENABLE_PUSH",
|
||||
SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
|
||||
SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
|
||||
SettingMaxFrameSize: "MAX_FRAME_SIZE",
|
||||
SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
|
||||
SettingHeaderTableSize: "HEADER_TABLE_SIZE",
|
||||
SettingEnablePush: "ENABLE_PUSH",
|
||||
SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
|
||||
SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
|
||||
SettingMaxFrameSize: "MAX_FRAME_SIZE",
|
||||
SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
|
||||
SettingEnableConnectProtocol: "ENABLE_CONNECT_PROTOCOL",
|
||||
}
|
||||
|
||||
func (s SettingID) String() string {
|
||||
@@ -210,12 +231,6 @@ type stringWriter interface {
|
||||
WriteString(s string) (n int, err error)
|
||||
}
|
||||
|
||||
// A gate lets two goroutines coordinate their activities.
|
||||
type gate chan struct{}
|
||||
|
||||
func (g gate) Done() { g <- struct{}{} }
|
||||
func (g gate) Wait() { <-g }
|
||||
|
||||
// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
|
||||
type closeWaiter chan struct{}
|
||||
|
||||
@@ -241,13 +256,19 @@ func (cw closeWaiter) Wait() {
|
||||
// Its buffered writer is lazily allocated as needed, to minimize
|
||||
// idle memory usage with many connections.
|
||||
type bufferedWriter struct {
|
||||
_ incomparable
|
||||
w io.Writer // immutable
|
||||
bw *bufio.Writer // non-nil when data is buffered
|
||||
_ incomparable
|
||||
group synctestGroupInterface // immutable
|
||||
conn net.Conn // immutable
|
||||
bw *bufio.Writer // non-nil when data is buffered
|
||||
byteTimeout time.Duration // immutable, WriteByteTimeout
|
||||
}
|
||||
|
||||
func newBufferedWriter(w io.Writer) *bufferedWriter {
|
||||
return &bufferedWriter{w: w}
|
||||
func newBufferedWriter(group synctestGroupInterface, conn net.Conn, timeout time.Duration) *bufferedWriter {
|
||||
return &bufferedWriter{
|
||||
group: group,
|
||||
conn: conn,
|
||||
byteTimeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// bufWriterPoolBufferSize is the size of bufio.Writer's
|
||||
@@ -274,7 +295,7 @@ func (w *bufferedWriter) Available() int {
|
||||
func (w *bufferedWriter) Write(p []byte) (n int, err error) {
|
||||
if w.bw == nil {
|
||||
bw := bufWriterPool.Get().(*bufio.Writer)
|
||||
bw.Reset(w.w)
|
||||
bw.Reset((*bufferedWriterTimeoutWriter)(w))
|
||||
w.bw = bw
|
||||
}
|
||||
return w.bw.Write(p)
|
||||
@@ -292,6 +313,38 @@ func (w *bufferedWriter) Flush() error {
|
||||
return err
|
||||
}
|
||||
|
||||
type bufferedWriterTimeoutWriter bufferedWriter
|
||||
|
||||
func (w *bufferedWriterTimeoutWriter) Write(p []byte) (n int, err error) {
|
||||
return writeWithByteTimeout(w.group, w.conn, w.byteTimeout, p)
|
||||
}
|
||||
|
||||
// writeWithByteTimeout writes to conn.
|
||||
// If more than timeout passes without any bytes being written to the connection,
|
||||
// the write fails.
|
||||
func writeWithByteTimeout(group synctestGroupInterface, conn net.Conn, timeout time.Duration, p []byte) (n int, err error) {
|
||||
if timeout <= 0 {
|
||||
return conn.Write(p)
|
||||
}
|
||||
for {
|
||||
var now time.Time
|
||||
if group == nil {
|
||||
now = time.Now()
|
||||
} else {
|
||||
now = group.Now()
|
||||
}
|
||||
conn.SetWriteDeadline(now.Add(timeout))
|
||||
nn, err := conn.Write(p[n:])
|
||||
n += nn
|
||||
if n == len(p) || nn == 0 || !errors.Is(err, os.ErrDeadlineExceeded) {
|
||||
// Either we finished the write, made no progress, or hit the deadline.
|
||||
// Whichever it is, we're done now.
|
||||
conn.SetWriteDeadline(time.Time{})
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mustUint31(v int32) uint32 {
|
||||
if v < 0 || v > 2147483647 {
|
||||
panic("out of range")
|
||||
@@ -362,24 +415,18 @@ func (s *sorter) SortStrings(ss []string) {
|
||||
s.v = save
|
||||
}
|
||||
|
||||
// validPseudoPath reports whether v is a valid :path pseudo-header
|
||||
// value. It must be either:
|
||||
//
|
||||
// - a non-empty string starting with '/'
|
||||
// - the string '*', for OPTIONS requests.
|
||||
//
|
||||
// For now this is only used a quick check for deciding when to clean
|
||||
// up Opaque URLs before sending requests from the Transport.
|
||||
// See golang.org/issue/16847
|
||||
//
|
||||
// We used to enforce that the path also didn't start with "//", but
|
||||
// Google's GFE accepts such paths and Chrome sends them, so ignore
|
||||
// that part of the spec. See golang.org/issue/19103.
|
||||
func validPseudoPath(v string) bool {
|
||||
return (len(v) > 0 && v[0] == '/') || v == "*"
|
||||
}
|
||||
|
||||
// incomparable is a zero-width, non-comparable type. Adding it to a struct
|
||||
// makes that struct also non-comparable, and generally doesn't add
|
||||
// any size (as long as it's first).
|
||||
type incomparable [0]func()
|
||||
|
||||
// synctestGroupInterface is the methods of synctestGroup used by Server and Transport.
|
||||
// It's defined as an interface here to let us keep synctestGroup entirely test-only
|
||||
// and not a part of non-test builds.
|
||||
type synctestGroupInterface interface {
|
||||
Join()
|
||||
Now() time.Time
|
||||
NewTimer(d time.Duration) timer
|
||||
AfterFunc(d time.Duration, f func()) timer
|
||||
ContextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc)
|
||||
}
|
||||
+254
-185
@@ -29,6 +29,7 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -49,13 +50,18 @@ import (
|
||||
|
||||
"golang.org/x/net/http/httpguts"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"golang.org/x/net/internal/httpcommon"
|
||||
)
|
||||
|
||||
const (
|
||||
prefaceTimeout = 10 * time.Second
|
||||
firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway
|
||||
handlerChunkWriteSize = 4 << 10
|
||||
defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?
|
||||
prefaceTimeout = 10 * time.Second
|
||||
firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway
|
||||
handlerChunkWriteSize = 4 << 10
|
||||
defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?
|
||||
|
||||
// maxQueuedControlFrames is the maximum number of control frames like
|
||||
// SETTINGS, PING and RST_STREAM that will be queued for writing before
|
||||
// the connection is closed to prevent memory exhaustion attacks.
|
||||
maxQueuedControlFrames = 10000
|
||||
)
|
||||
|
||||
@@ -127,6 +133,22 @@ type Server struct {
|
||||
// If zero or negative, there is no timeout.
|
||||
IdleTimeout time.Duration
|
||||
|
||||
// ReadIdleTimeout is the timeout after which a health check using a ping
|
||||
// frame will be carried out if no frame is received on the connection.
|
||||
// If zero, no health check is performed.
|
||||
ReadIdleTimeout time.Duration
|
||||
|
||||
// PingTimeout is the timeout after which the connection will be closed
|
||||
// if a response to a ping is not received.
|
||||
// If zero, a default of 15 seconds is used.
|
||||
PingTimeout time.Duration
|
||||
|
||||
// WriteByteTimeout is the timeout after which a connection will be
|
||||
// closed if no data can be written to it. The timeout begins when data is
|
||||
// available to write, and is extended whenever any bytes are written.
|
||||
// If zero or negative, there is no timeout.
|
||||
WriteByteTimeout time.Duration
|
||||
|
||||
// MaxUploadBufferPerConnection is the size of the initial flow
|
||||
// control window for each connections. The HTTP/2 spec does not
|
||||
// allow this to be smaller than 65535 or larger than 2^32-1.
|
||||
@@ -154,57 +176,39 @@ type Server struct {
|
||||
// so that we don't embed a Mutex in this struct, which will make the
|
||||
// struct non-copyable, which might break some callers.
|
||||
state *serverInternalState
|
||||
|
||||
// Synchronization group used for testing.
|
||||
// Outside of tests, this is nil.
|
||||
group synctestGroupInterface
|
||||
}
|
||||
|
||||
func (s *Server) initialConnRecvWindowSize() int32 {
|
||||
if s.MaxUploadBufferPerConnection >= initialWindowSize {
|
||||
return s.MaxUploadBufferPerConnection
|
||||
func (s *Server) markNewGoroutine() {
|
||||
if s.group != nil {
|
||||
s.group.Join()
|
||||
}
|
||||
return 1 << 20
|
||||
}
|
||||
|
||||
func (s *Server) initialStreamRecvWindowSize() int32 {
|
||||
if s.MaxUploadBufferPerStream > 0 {
|
||||
return s.MaxUploadBufferPerStream
|
||||
func (s *Server) now() time.Time {
|
||||
if s.group != nil {
|
||||
return s.group.Now()
|
||||
}
|
||||
return 1 << 20
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
func (s *Server) maxReadFrameSize() uint32 {
|
||||
if v := s.MaxReadFrameSize; v >= minMaxFrameSize && v <= maxFrameSize {
|
||||
return v
|
||||
// newTimer creates a new time.Timer, or a synthetic timer in tests.
|
||||
func (s *Server) newTimer(d time.Duration) timer {
|
||||
if s.group != nil {
|
||||
return s.group.NewTimer(d)
|
||||
}
|
||||
return defaultMaxReadFrameSize
|
||||
return timeTimer{time.NewTimer(d)}
|
||||
}
|
||||
|
||||
func (s *Server) maxConcurrentStreams() uint32 {
|
||||
if v := s.MaxConcurrentStreams; v > 0 {
|
||||
return v
|
||||
// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
|
||||
func (s *Server) afterFunc(d time.Duration, f func()) timer {
|
||||
if s.group != nil {
|
||||
return s.group.AfterFunc(d, f)
|
||||
}
|
||||
return defaultMaxStreams
|
||||
}
|
||||
|
||||
func (s *Server) maxDecoderHeaderTableSize() uint32 {
|
||||
if v := s.MaxDecoderHeaderTableSize; v > 0 {
|
||||
return v
|
||||
}
|
||||
return initialHeaderTableSize
|
||||
}
|
||||
|
||||
func (s *Server) maxEncoderHeaderTableSize() uint32 {
|
||||
if v := s.MaxEncoderHeaderTableSize; v > 0 {
|
||||
return v
|
||||
}
|
||||
return initialHeaderTableSize
|
||||
}
|
||||
|
||||
// maxQueuedControlFrames is the maximum number of control frames like
|
||||
// SETTINGS, PING and RST_STREAM that will be queued for writing before
|
||||
// the connection is closed to prevent memory exhaustion attacks.
|
||||
func (s *Server) maxQueuedControlFrames() int {
|
||||
// TODO: if anybody asks, add a Server field, and remember to define the
|
||||
// behavior of negative values.
|
||||
return maxQueuedControlFrames
|
||||
return timeTimer{time.AfterFunc(d, f)}
|
||||
}
|
||||
|
||||
type serverInternalState struct {
|
||||
@@ -303,7 +307,7 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
||||
if s.TLSNextProto == nil {
|
||||
s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
|
||||
}
|
||||
protoHandler := func(hs *http.Server, c *tls.Conn, h http.Handler) {
|
||||
protoHandler := func(hs *http.Server, c net.Conn, h http.Handler, sawClientPreface bool) {
|
||||
if testHookOnConn != nil {
|
||||
testHookOnConn()
|
||||
}
|
||||
@@ -320,12 +324,31 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
||||
ctx = bc.BaseContext()
|
||||
}
|
||||
conf.ServeConn(c, &ServeConnOpts{
|
||||
Context: ctx,
|
||||
Handler: h,
|
||||
BaseConfig: hs,
|
||||
Context: ctx,
|
||||
Handler: h,
|
||||
BaseConfig: hs,
|
||||
SawClientPreface: sawClientPreface,
|
||||
})
|
||||
}
|
||||
s.TLSNextProto[NextProtoTLS] = protoHandler
|
||||
s.TLSNextProto[NextProtoTLS] = func(hs *http.Server, c *tls.Conn, h http.Handler) {
|
||||
protoHandler(hs, c, h, false)
|
||||
}
|
||||
// The "unencrypted_http2" TLSNextProto key is used to pass off non-TLS HTTP/2 conns.
|
||||
//
|
||||
// A connection passed in this method has already had the HTTP/2 preface read from it.
|
||||
s.TLSNextProto[nextProtoUnencryptedHTTP2] = func(hs *http.Server, c *tls.Conn, h http.Handler) {
|
||||
nc, err := unencryptedNetConnFromTLSConn(c)
|
||||
if err != nil {
|
||||
if lg := hs.ErrorLog; lg != nil {
|
||||
lg.Print(err)
|
||||
} else {
|
||||
log.Print(err)
|
||||
}
|
||||
go c.Close()
|
||||
return
|
||||
}
|
||||
protoHandler(hs, nc, h, true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -400,16 +423,22 @@ func (o *ServeConnOpts) handler() http.Handler {
|
||||
//
|
||||
// The opts parameter is optional. If nil, default values are used.
|
||||
func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||
s.serveConn(c, opts, nil)
|
||||
}
|
||||
|
||||
func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverConn)) {
|
||||
baseCtx, cancel := serverConnBaseContext(c, opts)
|
||||
defer cancel()
|
||||
|
||||
http1srv := opts.baseConfig()
|
||||
conf := configFromServer(http1srv, s)
|
||||
sc := &serverConn{
|
||||
srv: s,
|
||||
hs: opts.baseConfig(),
|
||||
hs: http1srv,
|
||||
conn: c,
|
||||
baseCtx: baseCtx,
|
||||
remoteAddrStr: c.RemoteAddr().String(),
|
||||
bw: newBufferedWriter(c),
|
||||
bw: newBufferedWriter(s.group, c, conf.WriteByteTimeout),
|
||||
handler: opts.handler(),
|
||||
streams: make(map[uint32]*stream),
|
||||
readFrameCh: make(chan readFrameResult),
|
||||
@@ -419,13 +448,19 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||
bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
|
||||
doneServing: make(chan struct{}),
|
||||
clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
|
||||
advMaxStreams: s.maxConcurrentStreams(),
|
||||
advMaxStreams: conf.MaxConcurrentStreams,
|
||||
initialStreamSendWindowSize: initialWindowSize,
|
||||
initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream,
|
||||
maxFrameSize: initialMaxFrameSize,
|
||||
pingTimeout: conf.PingTimeout,
|
||||
countErrorFunc: conf.CountError,
|
||||
serveG: newGoroutineLock(),
|
||||
pushEnabled: true,
|
||||
sawClientPreface: opts.SawClientPreface,
|
||||
}
|
||||
if newf != nil {
|
||||
newf(sc)
|
||||
}
|
||||
|
||||
s.state.registerConn(sc)
|
||||
defer s.state.unregisterConn(sc)
|
||||
@@ -451,15 +486,15 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||
sc.flow.add(initialWindowSize)
|
||||
sc.inflow.init(initialWindowSize)
|
||||
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
|
||||
sc.hpackEncoder.SetMaxDynamicTableSizeLimit(s.maxEncoderHeaderTableSize())
|
||||
sc.hpackEncoder.SetMaxDynamicTableSizeLimit(conf.MaxEncoderHeaderTableSize)
|
||||
|
||||
fr := NewFramer(sc.bw, c)
|
||||
if s.CountError != nil {
|
||||
fr.countError = s.CountError
|
||||
if conf.CountError != nil {
|
||||
fr.countError = conf.CountError
|
||||
}
|
||||
fr.ReadMetaHeaders = hpack.NewDecoder(s.maxDecoderHeaderTableSize(), nil)
|
||||
fr.ReadMetaHeaders = hpack.NewDecoder(conf.MaxDecoderHeaderTableSize, nil)
|
||||
fr.MaxHeaderListSize = sc.maxHeaderListSize()
|
||||
fr.SetMaxReadFrameSize(s.maxReadFrameSize())
|
||||
fr.SetMaxReadFrameSize(conf.MaxReadFrameSize)
|
||||
sc.framer = fr
|
||||
|
||||
if tc, ok := c.(connectionStater); ok {
|
||||
@@ -492,7 +527,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||
// So for now, do nothing here again.
|
||||
}
|
||||
|
||||
if !s.PermitProhibitedCipherSuites && isBadCipher(sc.tlsState.CipherSuite) {
|
||||
if !conf.PermitProhibitedCipherSuites && isBadCipher(sc.tlsState.CipherSuite) {
|
||||
// "Endpoints MAY choose to generate a connection error
|
||||
// (Section 5.4.1) of type INADEQUATE_SECURITY if one of
|
||||
// the prohibited cipher suites are negotiated."
|
||||
@@ -529,7 +564,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||
opts.UpgradeRequest = nil
|
||||
}
|
||||
|
||||
sc.serve()
|
||||
sc.serve(conf)
|
||||
}
|
||||
|
||||
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx context.Context, cancel func()) {
|
||||
@@ -569,6 +604,7 @@ type serverConn struct {
|
||||
tlsState *tls.ConnectionState // shared by all handlers, like net/http
|
||||
remoteAddrStr string
|
||||
writeSched WriteScheduler
|
||||
countErrorFunc func(errType string)
|
||||
|
||||
// Everything following is owned by the serve loop; use serveG.check():
|
||||
serveG goroutineLock // used to verify funcs are on serve()
|
||||
@@ -588,6 +624,7 @@ type serverConn struct {
|
||||
streams map[uint32]*stream
|
||||
unstartedHandlers []unstartedHandler
|
||||
initialStreamSendWindowSize int32
|
||||
initialStreamRecvWindowSize int32
|
||||
maxFrameSize int32
|
||||
peerMaxHeaderListSize uint32 // zero means unknown (default)
|
||||
canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
|
||||
@@ -598,9 +635,14 @@ type serverConn struct {
|
||||
inGoAway bool // we've started to or sent GOAWAY
|
||||
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
|
||||
needToSendGoAway bool // we need to schedule a GOAWAY frame write
|
||||
pingSent bool
|
||||
sentPingData [8]byte
|
||||
goAwayCode ErrCode
|
||||
shutdownTimer *time.Timer // nil until used
|
||||
idleTimer *time.Timer // nil if unused
|
||||
shutdownTimer timer // nil until used
|
||||
idleTimer timer // nil if unused
|
||||
readIdleTimeout time.Duration
|
||||
pingTimeout time.Duration
|
||||
readIdleTimer timer // nil if unused
|
||||
|
||||
// Owned by the writeFrameAsync goroutine:
|
||||
headerWriteBuf bytes.Buffer
|
||||
@@ -615,11 +657,7 @@ func (sc *serverConn) maxHeaderListSize() uint32 {
|
||||
if n <= 0 {
|
||||
n = http.DefaultMaxHeaderBytes
|
||||
}
|
||||
// http2's count is in a slightly different unit and includes 32 bytes per pair.
|
||||
// So, take the net/http.Server value and pad it up a bit, assuming 10 headers.
|
||||
const perFieldOverhead = 32 // per http2 spec
|
||||
const typicalHeaders = 10 // conservative
|
||||
return uint32(n + typicalHeaders*perFieldOverhead)
|
||||
return uint32(adjustHTTP1MaxHeaderSize(int64(n)))
|
||||
}
|
||||
|
||||
func (sc *serverConn) curOpenStreams() uint32 {
|
||||
@@ -649,12 +687,12 @@ type stream struct {
|
||||
flow outflow // limits writing from Handler to client
|
||||
inflow inflow // what the client is allowed to POST/etc to us
|
||||
state streamState
|
||||
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
|
||||
gotTrailerHeader bool // HEADER frame for trailers was seen
|
||||
wroteHeaders bool // whether we wrote headers (not status 100)
|
||||
readDeadline *time.Timer // nil if unused
|
||||
writeDeadline *time.Timer // nil if unused
|
||||
closeErr error // set before cw is closed
|
||||
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
|
||||
gotTrailerHeader bool // HEADER frame for trailers was seen
|
||||
wroteHeaders bool // whether we wrote headers (not status 100)
|
||||
readDeadline timer // nil if unused
|
||||
writeDeadline timer // nil if unused
|
||||
closeErr error // set before cw is closed
|
||||
|
||||
trailer http.Header // accumulated trailers
|
||||
reqTrailer http.Header // handler's Request.Trailer
|
||||
@@ -732,11 +770,7 @@ func isClosedConnError(err error) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: remove this string search and be more like the Windows
|
||||
// case below. That might involve modifying the standard library
|
||||
// to return better error types.
|
||||
str := err.Error()
|
||||
if strings.Contains(str, "use of closed network connection") {
|
||||
if errors.Is(err, net.ErrClosed) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -779,8 +813,7 @@ const maxCachedCanonicalHeadersKeysSize = 2048
|
||||
|
||||
func (sc *serverConn) canonicalHeader(v string) string {
|
||||
sc.serveG.check()
|
||||
buildCommonHeaderMapsOnce()
|
||||
cv, ok := commonCanonHeader[v]
|
||||
cv, ok := httpcommon.CachedCanonicalHeader(v)
|
||||
if ok {
|
||||
return cv
|
||||
}
|
||||
@@ -815,8 +848,9 @@ type readFrameResult struct {
|
||||
// consumer is done with the frame.
|
||||
// It's run on its own goroutine.
|
||||
func (sc *serverConn) readFrames() {
|
||||
gate := make(gate)
|
||||
gateDone := gate.Done
|
||||
sc.srv.markNewGoroutine()
|
||||
gate := make(chan struct{})
|
||||
gateDone := func() { gate <- struct{}{} }
|
||||
for {
|
||||
f, err := sc.framer.ReadFrame()
|
||||
select {
|
||||
@@ -847,6 +881,7 @@ type frameWriteResult struct {
|
||||
// At most one goroutine can be running writeFrameAsync at a time per
|
||||
// serverConn.
|
||||
func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest, wd *writeData) {
|
||||
sc.srv.markNewGoroutine()
|
||||
var err error
|
||||
if wd == nil {
|
||||
err = wr.write.writeFrame(sc)
|
||||
@@ -885,7 +920,7 @@ func (sc *serverConn) notePanic() {
|
||||
}
|
||||
}
|
||||
|
||||
func (sc *serverConn) serve() {
|
||||
func (sc *serverConn) serve(conf http2Config) {
|
||||
sc.serveG.check()
|
||||
defer sc.notePanic()
|
||||
defer sc.conn.Close()
|
||||
@@ -897,20 +932,24 @@ func (sc *serverConn) serve() {
|
||||
sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
|
||||
}
|
||||
|
||||
settings := writeSettings{
|
||||
{SettingMaxFrameSize, conf.MaxReadFrameSize},
|
||||
{SettingMaxConcurrentStreams, sc.advMaxStreams},
|
||||
{SettingMaxHeaderListSize, sc.maxHeaderListSize()},
|
||||
{SettingHeaderTableSize, conf.MaxDecoderHeaderTableSize},
|
||||
{SettingInitialWindowSize, uint32(sc.initialStreamRecvWindowSize)},
|
||||
}
|
||||
if !disableExtendedConnectProtocol {
|
||||
settings = append(settings, Setting{SettingEnableConnectProtocol, 1})
|
||||
}
|
||||
sc.writeFrame(FrameWriteRequest{
|
||||
write: writeSettings{
|
||||
{SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
|
||||
{SettingMaxConcurrentStreams, sc.advMaxStreams},
|
||||
{SettingMaxHeaderListSize, sc.maxHeaderListSize()},
|
||||
{SettingHeaderTableSize, sc.srv.maxDecoderHeaderTableSize()},
|
||||
{SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())},
|
||||
},
|
||||
write: settings,
|
||||
})
|
||||
sc.unackedSettings++
|
||||
|
||||
// Each connection starts with initialWindowSize inflow tokens.
|
||||
// If a higher value is configured, we add more tokens.
|
||||
if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
|
||||
if diff := conf.MaxUploadBufferPerConnection - initialWindowSize; diff > 0 {
|
||||
sc.sendWindowUpdate(nil, int(diff))
|
||||
}
|
||||
|
||||
@@ -926,15 +965,22 @@ func (sc *serverConn) serve() {
|
||||
sc.setConnState(http.StateIdle)
|
||||
|
||||
if sc.srv.IdleTimeout > 0 {
|
||||
sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
|
||||
sc.idleTimer = sc.srv.afterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
|
||||
defer sc.idleTimer.Stop()
|
||||
}
|
||||
|
||||
if conf.SendPingTimeout > 0 {
|
||||
sc.readIdleTimeout = conf.SendPingTimeout
|
||||
sc.readIdleTimer = sc.srv.afterFunc(conf.SendPingTimeout, sc.onReadIdleTimer)
|
||||
defer sc.readIdleTimer.Stop()
|
||||
}
|
||||
|
||||
go sc.readFrames() // closed by defer sc.conn.Close above
|
||||
|
||||
settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer)
|
||||
settingsTimer := sc.srv.afterFunc(firstSettingsTimeout, sc.onSettingsTimer)
|
||||
defer settingsTimer.Stop()
|
||||
|
||||
lastFrameTime := sc.srv.now()
|
||||
loopNum := 0
|
||||
for {
|
||||
loopNum++
|
||||
@@ -948,6 +994,7 @@ func (sc *serverConn) serve() {
|
||||
case res := <-sc.wroteFrameCh:
|
||||
sc.wroteFrame(res)
|
||||
case res := <-sc.readFrameCh:
|
||||
lastFrameTime = sc.srv.now()
|
||||
// Process any written frames before reading new frames from the client since a
|
||||
// written frame could have triggered a new stream to be started.
|
||||
if sc.writingFrameAsync {
|
||||
@@ -979,6 +1026,8 @@ func (sc *serverConn) serve() {
|
||||
case idleTimerMsg:
|
||||
sc.vlogf("connection is idle")
|
||||
sc.goAway(ErrCodeNo)
|
||||
case readIdleTimerMsg:
|
||||
sc.handlePingTimer(lastFrameTime)
|
||||
case shutdownTimerMsg:
|
||||
sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
|
||||
return
|
||||
@@ -1001,7 +1050,7 @@ func (sc *serverConn) serve() {
|
||||
// If the peer is causing us to generate a lot of control frames,
|
||||
// but not reading them from us, assume they are trying to make us
|
||||
// run out of memory.
|
||||
if sc.queuedControlFrames > sc.srv.maxQueuedControlFrames() {
|
||||
if sc.queuedControlFrames > maxQueuedControlFrames {
|
||||
sc.vlogf("http2: too many control frames in send queue, closing connection")
|
||||
return
|
||||
}
|
||||
@@ -1017,12 +1066,42 @@ func (sc *serverConn) serve() {
|
||||
}
|
||||
}
|
||||
|
||||
func (sc *serverConn) handlePingTimer(lastFrameReadTime time.Time) {
|
||||
if sc.pingSent {
|
||||
sc.logf("timeout waiting for PING response")
|
||||
if f := sc.countErrorFunc; f != nil {
|
||||
f("conn_close_lost_ping")
|
||||
}
|
||||
sc.conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
pingAt := lastFrameReadTime.Add(sc.readIdleTimeout)
|
||||
now := sc.srv.now()
|
||||
if pingAt.After(now) {
|
||||
// We received frames since arming the ping timer.
|
||||
// Reset it for the next possible timeout.
|
||||
sc.readIdleTimer.Reset(pingAt.Sub(now))
|
||||
return
|
||||
}
|
||||
|
||||
sc.pingSent = true
|
||||
// Ignore crypto/rand.Read errors: It generally can't fail, and worse case if it does
|
||||
// is we send a PING frame containing 0s.
|
||||
_, _ = rand.Read(sc.sentPingData[:])
|
||||
sc.writeFrame(FrameWriteRequest{
|
||||
write: &writePing{data: sc.sentPingData},
|
||||
})
|
||||
sc.readIdleTimer.Reset(sc.pingTimeout)
|
||||
}
|
||||
|
||||
type serverMessage int
|
||||
|
||||
// Message values sent to serveMsgCh.
|
||||
var (
|
||||
settingsTimerMsg = new(serverMessage)
|
||||
idleTimerMsg = new(serverMessage)
|
||||
readIdleTimerMsg = new(serverMessage)
|
||||
shutdownTimerMsg = new(serverMessage)
|
||||
gracefulShutdownMsg = new(serverMessage)
|
||||
handlerDoneMsg = new(serverMessage)
|
||||
@@ -1030,6 +1109,7 @@ var (
|
||||
|
||||
func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }
|
||||
func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) }
|
||||
func (sc *serverConn) onReadIdleTimer() { sc.sendServeMsg(readIdleTimerMsg) }
|
||||
func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) }
|
||||
|
||||
func (sc *serverConn) sendServeMsg(msg interface{}) {
|
||||
@@ -1061,10 +1141,10 @@ func (sc *serverConn) readPreface() error {
|
||||
errc <- nil
|
||||
}
|
||||
}()
|
||||
timer := time.NewTimer(prefaceTimeout) // TODO: configurable on *Server?
|
||||
timer := sc.srv.newTimer(prefaceTimeout) // TODO: configurable on *Server?
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case <-timer.C:
|
||||
case <-timer.C():
|
||||
return errPrefaceTimeout
|
||||
case err := <-errc:
|
||||
if err == nil {
|
||||
@@ -1282,6 +1362,10 @@ func (sc *serverConn) wroteFrame(res frameWriteResult) {
|
||||
sc.writingFrame = false
|
||||
sc.writingFrameAsync = false
|
||||
|
||||
if res.err != nil {
|
||||
sc.conn.Close()
|
||||
}
|
||||
|
||||
wr := res.wr
|
||||
|
||||
if writeEndsStream(wr.write) {
|
||||
@@ -1429,7 +1513,7 @@ func (sc *serverConn) goAway(code ErrCode) {
|
||||
|
||||
func (sc *serverConn) shutDownIn(d time.Duration) {
|
||||
sc.serveG.check()
|
||||
sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer)
|
||||
sc.shutdownTimer = sc.srv.afterFunc(d, sc.onShutdownTimer)
|
||||
}
|
||||
|
||||
func (sc *serverConn) resetStream(se StreamError) {
|
||||
@@ -1482,6 +1566,11 @@ func (sc *serverConn) processFrameFromReader(res readFrameResult) bool {
|
||||
sc.goAway(ErrCodeFlowControl)
|
||||
return true
|
||||
case ConnectionError:
|
||||
if res.f != nil {
|
||||
if id := res.f.Header().StreamID; id > sc.maxClientStreamID {
|
||||
sc.maxClientStreamID = id
|
||||
}
|
||||
}
|
||||
sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev)
|
||||
sc.goAway(ErrCode(ev))
|
||||
return true // goAway will handle shutdown
|
||||
@@ -1551,6 +1640,11 @@ func (sc *serverConn) processFrame(f Frame) error {
|
||||
func (sc *serverConn) processPing(f *PingFrame) error {
|
||||
sc.serveG.check()
|
||||
if f.IsAck() {
|
||||
if sc.pingSent && sc.sentPingData == f.Data {
|
||||
// This is a response to a PING we sent.
|
||||
sc.pingSent = false
|
||||
sc.readIdleTimer.Reset(sc.readIdleTimeout)
|
||||
}
|
||||
// 6.7 PING: " An endpoint MUST NOT respond to PING frames
|
||||
// containing this flag."
|
||||
return nil
|
||||
@@ -1638,7 +1732,7 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
||||
delete(sc.streams, st.id)
|
||||
if len(sc.streams) == 0 {
|
||||
sc.setConnState(http.StateIdle)
|
||||
if sc.srv.IdleTimeout > 0 {
|
||||
if sc.srv.IdleTimeout > 0 && sc.idleTimer != nil {
|
||||
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
||||
}
|
||||
if h1ServerKeepAlivesDisabled(sc.hs) {
|
||||
@@ -1660,6 +1754,7 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
||||
}
|
||||
}
|
||||
st.closeErr = err
|
||||
st.cancelCtx()
|
||||
st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
|
||||
sc.writeSched.CloseStream(st.id)
|
||||
}
|
||||
@@ -1713,6 +1808,9 @@ func (sc *serverConn) processSetting(s Setting) error {
|
||||
sc.maxFrameSize = int32(s.Val) // the maximum valid s.Val is < 2^31
|
||||
case SettingMaxHeaderListSize:
|
||||
sc.peerMaxHeaderListSize = s.Val
|
||||
case SettingEnableConnectProtocol:
|
||||
// Receipt of this parameter by a server does not
|
||||
// have any impact
|
||||
default:
|
||||
// Unknown setting: "An endpoint that receives a SETTINGS
|
||||
// frame with any unknown or unsupported identifier MUST
|
||||
@@ -2020,7 +2118,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
||||
// (in Go 1.8), though. That's a more sane option anyway.
|
||||
if sc.hs.ReadTimeout > 0 {
|
||||
sc.conn.SetReadDeadline(time.Time{})
|
||||
st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
|
||||
st.readDeadline = sc.srv.afterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
|
||||
}
|
||||
|
||||
return sc.scheduleHandler(id, rw, req, handler)
|
||||
@@ -2116,9 +2214,9 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
|
||||
st.cw.Init()
|
||||
st.flow.conn = &sc.flow // link to conn-level counter
|
||||
st.flow.add(sc.initialStreamSendWindowSize)
|
||||
st.inflow.init(sc.srv.initialStreamRecvWindowSize())
|
||||
st.inflow.init(sc.initialStreamRecvWindowSize)
|
||||
if sc.hs.WriteTimeout > 0 {
|
||||
st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
|
||||
st.writeDeadline = sc.srv.afterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
|
||||
}
|
||||
|
||||
sc.streams[id] = st
|
||||
@@ -2138,19 +2236,25 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
|
||||
func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*responseWriter, *http.Request, error) {
|
||||
sc.serveG.check()
|
||||
|
||||
rp := requestParam{
|
||||
method: f.PseudoValue("method"),
|
||||
scheme: f.PseudoValue("scheme"),
|
||||
authority: f.PseudoValue("authority"),
|
||||
path: f.PseudoValue("path"),
|
||||
rp := httpcommon.ServerRequestParam{
|
||||
Method: f.PseudoValue("method"),
|
||||
Scheme: f.PseudoValue("scheme"),
|
||||
Authority: f.PseudoValue("authority"),
|
||||
Path: f.PseudoValue("path"),
|
||||
Protocol: f.PseudoValue("protocol"),
|
||||
}
|
||||
|
||||
isConnect := rp.method == "CONNECT"
|
||||
// extended connect is disabled, so we should not see :protocol
|
||||
if disableExtendedConnectProtocol && rp.Protocol != "" {
|
||||
return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol))
|
||||
}
|
||||
|
||||
isConnect := rp.Method == "CONNECT"
|
||||
if isConnect {
|
||||
if rp.path != "" || rp.scheme != "" || rp.authority == "" {
|
||||
if rp.Protocol == "" && (rp.Path != "" || rp.Scheme != "" || rp.Authority == "") {
|
||||
return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol))
|
||||
}
|
||||
} else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
|
||||
} else if rp.Method == "" || rp.Path == "" || (rp.Scheme != "https" && rp.Scheme != "http") {
|
||||
// See 8.1.2.6 Malformed Requests and Responses:
|
||||
//
|
||||
// Malformed requests or responses that are detected
|
||||
@@ -2164,12 +2268,16 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
||||
return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol))
|
||||
}
|
||||
|
||||
rp.header = make(http.Header)
|
||||
header := make(http.Header)
|
||||
rp.Header = header
|
||||
for _, hf := range f.RegularFields() {
|
||||
rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value)
|
||||
header.Add(sc.canonicalHeader(hf.Name), hf.Value)
|
||||
}
|
||||
if rp.authority == "" {
|
||||
rp.authority = rp.header.Get("Host")
|
||||
if rp.Authority == "" {
|
||||
rp.Authority = header.Get("Host")
|
||||
}
|
||||
if rp.Protocol != "" {
|
||||
header.Set(":protocol", rp.Protocol)
|
||||
}
|
||||
|
||||
rw, req, err := sc.newWriterAndRequestNoBody(st, rp)
|
||||
@@ -2178,7 +2286,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
||||
}
|
||||
bodyOpen := !f.StreamEnded()
|
||||
if bodyOpen {
|
||||
if vv, ok := rp.header["Content-Length"]; ok {
|
||||
if vv, ok := rp.Header["Content-Length"]; ok {
|
||||
if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil {
|
||||
req.ContentLength = int64(cl)
|
||||
} else {
|
||||
@@ -2194,83 +2302,38 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
||||
return rw, req, nil
|
||||
}
|
||||
|
||||
type requestParam struct {
|
||||
method string
|
||||
scheme, authority, path string
|
||||
header http.Header
|
||||
}
|
||||
|
||||
func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*responseWriter, *http.Request, error) {
|
||||
func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp httpcommon.ServerRequestParam) (*responseWriter, *http.Request, error) {
|
||||
sc.serveG.check()
|
||||
|
||||
var tlsState *tls.ConnectionState // nil if not scheme https
|
||||
if rp.scheme == "https" {
|
||||
if rp.Scheme == "https" {
|
||||
tlsState = sc.tlsState
|
||||
}
|
||||
|
||||
needsContinue := httpguts.HeaderValuesContainsToken(rp.header["Expect"], "100-continue")
|
||||
if needsContinue {
|
||||
rp.header.Del("Expect")
|
||||
}
|
||||
// Merge Cookie headers into one "; "-delimited value.
|
||||
if cookies := rp.header["Cookie"]; len(cookies) > 1 {
|
||||
rp.header.Set("Cookie", strings.Join(cookies, "; "))
|
||||
}
|
||||
|
||||
// Setup Trailers
|
||||
var trailer http.Header
|
||||
for _, v := range rp.header["Trailer"] {
|
||||
for _, key := range strings.Split(v, ",") {
|
||||
key = http.CanonicalHeaderKey(textproto.TrimString(key))
|
||||
switch key {
|
||||
case "Transfer-Encoding", "Trailer", "Content-Length":
|
||||
// Bogus. (copy of http1 rules)
|
||||
// Ignore.
|
||||
default:
|
||||
if trailer == nil {
|
||||
trailer = make(http.Header)
|
||||
}
|
||||
trailer[key] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
delete(rp.header, "Trailer")
|
||||
|
||||
var url_ *url.URL
|
||||
var requestURI string
|
||||
if rp.method == "CONNECT" {
|
||||
url_ = &url.URL{Host: rp.authority}
|
||||
requestURI = rp.authority // mimic HTTP/1 server behavior
|
||||
} else {
|
||||
var err error
|
||||
url_, err = url.ParseRequestURI(rp.path)
|
||||
if err != nil {
|
||||
return nil, nil, sc.countError("bad_path", streamError(st.id, ErrCodeProtocol))
|
||||
}
|
||||
requestURI = rp.path
|
||||
res := httpcommon.NewServerRequest(rp)
|
||||
if res.InvalidReason != "" {
|
||||
return nil, nil, sc.countError(res.InvalidReason, streamError(st.id, ErrCodeProtocol))
|
||||
}
|
||||
|
||||
body := &requestBody{
|
||||
conn: sc,
|
||||
stream: st,
|
||||
needsContinue: needsContinue,
|
||||
needsContinue: res.NeedsContinue,
|
||||
}
|
||||
req := &http.Request{
|
||||
Method: rp.method,
|
||||
URL: url_,
|
||||
req := (&http.Request{
|
||||
Method: rp.Method,
|
||||
URL: res.URL,
|
||||
RemoteAddr: sc.remoteAddrStr,
|
||||
Header: rp.header,
|
||||
RequestURI: requestURI,
|
||||
Header: rp.Header,
|
||||
RequestURI: res.RequestURI,
|
||||
Proto: "HTTP/2.0",
|
||||
ProtoMajor: 2,
|
||||
ProtoMinor: 0,
|
||||
TLS: tlsState,
|
||||
Host: rp.authority,
|
||||
Host: rp.Authority,
|
||||
Body: body,
|
||||
Trailer: trailer,
|
||||
}
|
||||
req = req.WithContext(st.ctx)
|
||||
|
||||
Trailer: res.Trailer,
|
||||
}).WithContext(st.ctx)
|
||||
rw := sc.newResponseWriter(st, req)
|
||||
return rw, req, nil
|
||||
}
|
||||
@@ -2342,6 +2405,7 @@ func (sc *serverConn) handlerDone() {
|
||||
|
||||
// Run on its own goroutine.
|
||||
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
|
||||
sc.srv.markNewGoroutine()
|
||||
defer sc.sendServeMsg(handlerDoneMsg)
|
||||
didPanic := true
|
||||
defer func() {
|
||||
@@ -2638,7 +2702,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||
var date string
|
||||
if _, ok := rws.snapHeader["Date"]; !ok {
|
||||
// TODO(bradfitz): be faster here, like net/http? measure.
|
||||
date = time.Now().UTC().Format(http.TimeFormat)
|
||||
date = rws.conn.srv.now().UTC().Format(http.TimeFormat)
|
||||
}
|
||||
|
||||
for _, v := range rws.snapHeader["Trailer"] {
|
||||
@@ -2760,7 +2824,7 @@ func (rws *responseWriterState) promoteUndeclaredTrailers() {
|
||||
|
||||
func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
|
||||
st := w.rws.stream
|
||||
if !deadline.IsZero() && deadline.Before(time.Now()) {
|
||||
if !deadline.IsZero() && deadline.Before(w.rws.conn.srv.now()) {
|
||||
// If we're setting a deadline in the past, reset the stream immediately
|
||||
// so writes after SetWriteDeadline returns will fail.
|
||||
st.onReadTimeout()
|
||||
@@ -2776,9 +2840,9 @@ func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
|
||||
if deadline.IsZero() {
|
||||
st.readDeadline = nil
|
||||
} else if st.readDeadline == nil {
|
||||
st.readDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onReadTimeout)
|
||||
st.readDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onReadTimeout)
|
||||
} else {
|
||||
st.readDeadline.Reset(deadline.Sub(time.Now()))
|
||||
st.readDeadline.Reset(deadline.Sub(sc.srv.now()))
|
||||
}
|
||||
})
|
||||
return nil
|
||||
@@ -2786,7 +2850,7 @@ func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
|
||||
|
||||
func (w *responseWriter) SetWriteDeadline(deadline time.Time) error {
|
||||
st := w.rws.stream
|
||||
if !deadline.IsZero() && deadline.Before(time.Now()) {
|
||||
if !deadline.IsZero() && deadline.Before(w.rws.conn.srv.now()) {
|
||||
// If we're setting a deadline in the past, reset the stream immediately
|
||||
// so writes after SetWriteDeadline returns will fail.
|
||||
st.onWriteTimeout()
|
||||
@@ -2802,14 +2866,19 @@ func (w *responseWriter) SetWriteDeadline(deadline time.Time) error {
|
||||
if deadline.IsZero() {
|
||||
st.writeDeadline = nil
|
||||
} else if st.writeDeadline == nil {
|
||||
st.writeDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onWriteTimeout)
|
||||
st.writeDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onWriteTimeout)
|
||||
} else {
|
||||
st.writeDeadline.Reset(deadline.Sub(time.Now()))
|
||||
st.writeDeadline.Reset(deadline.Sub(sc.srv.now()))
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *responseWriter) EnableFullDuplex() error {
|
||||
// We always support full duplex responses, so this is a no-op.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *responseWriter) Flush() {
|
||||
w.FlushError()
|
||||
}
|
||||
@@ -3159,12 +3228,12 @@ func (sc *serverConn) startPush(msg *startPushRequest) {
|
||||
// we start in "half closed (remote)" for simplicity.
|
||||
// See further comments at the definition of stateHalfClosedRemote.
|
||||
promised := sc.newStream(promisedID, msg.parent.id, stateHalfClosedRemote)
|
||||
rw, req, err := sc.newWriterAndRequestNoBody(promised, requestParam{
|
||||
method: msg.method,
|
||||
scheme: msg.url.Scheme,
|
||||
authority: msg.url.Host,
|
||||
path: msg.url.RequestURI(),
|
||||
header: cloneHeader(msg.header), // clone since handler runs concurrently with writing the PUSH_PROMISE
|
||||
rw, req, err := sc.newWriterAndRequestNoBody(promised, httpcommon.ServerRequestParam{
|
||||
Method: msg.method,
|
||||
Scheme: msg.url.Scheme,
|
||||
Authority: msg.url.Host,
|
||||
Path: msg.url.RequestURI(),
|
||||
Header: cloneHeader(msg.header), // clone since handler runs concurrently with writing the PUSH_PROMISE
|
||||
})
|
||||
if err != nil {
|
||||
// Should not happen, since we've already validated msg.url.
|
||||
@@ -3256,7 +3325,7 @@ func (sc *serverConn) countError(name string, err error) error {
|
||||
if sc == nil || sc.srv == nil {
|
||||
return err
|
||||
}
|
||||
f := sc.srv.CountError
|
||||
f := sc.countErrorFunc
|
||||
if f == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
-331
@@ -1,331 +0,0 @@
|
||||
// Copyright 2024 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 http2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// testSyncHooks coordinates goroutines in tests.
|
||||
//
|
||||
// For example, a call to ClientConn.RoundTrip involves several goroutines, including:
|
||||
// - the goroutine running RoundTrip;
|
||||
// - the clientStream.doRequest goroutine, which writes the request; and
|
||||
// - the clientStream.readLoop goroutine, which reads the response.
|
||||
//
|
||||
// Using testSyncHooks, a test can start a RoundTrip and identify when all these goroutines
|
||||
// are blocked waiting for some condition such as reading the Request.Body or waiting for
|
||||
// flow control to become available.
|
||||
//
|
||||
// The testSyncHooks also manage timers and synthetic time in tests.
|
||||
// This permits us to, for example, start a request and cause it to time out waiting for
|
||||
// response headers without resorting to time.Sleep calls.
|
||||
type testSyncHooks struct {
|
||||
// active/inactive act as a mutex and condition variable.
|
||||
//
|
||||
// - neither chan contains a value: testSyncHooks is locked.
|
||||
// - active contains a value: unlocked, and at least one goroutine is not blocked
|
||||
// - inactive contains a value: unlocked, and all goroutines are blocked
|
||||
active chan struct{}
|
||||
inactive chan struct{}
|
||||
|
||||
// goroutine counts
|
||||
total int // total goroutines
|
||||
condwait map[*sync.Cond]int // blocked in sync.Cond.Wait
|
||||
blocked []*testBlockedGoroutine // otherwise blocked
|
||||
|
||||
// fake time
|
||||
now time.Time
|
||||
timers []*fakeTimer
|
||||
|
||||
// Transport testing: Report various events.
|
||||
newclientconn func(*ClientConn)
|
||||
newstream func(*clientStream)
|
||||
}
|
||||
|
||||
// testBlockedGoroutine is a blocked goroutine.
|
||||
type testBlockedGoroutine struct {
|
||||
f func() bool // blocked until f returns true
|
||||
ch chan struct{} // closed when unblocked
|
||||
}
|
||||
|
||||
func newTestSyncHooks() *testSyncHooks {
|
||||
h := &testSyncHooks{
|
||||
active: make(chan struct{}, 1),
|
||||
inactive: make(chan struct{}, 1),
|
||||
condwait: map[*sync.Cond]int{},
|
||||
}
|
||||
h.inactive <- struct{}{}
|
||||
h.now = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
return h
|
||||
}
|
||||
|
||||
// lock acquires the testSyncHooks mutex.
|
||||
func (h *testSyncHooks) lock() {
|
||||
select {
|
||||
case <-h.active:
|
||||
case <-h.inactive:
|
||||
}
|
||||
}
|
||||
|
||||
// waitInactive waits for all goroutines to become inactive.
|
||||
func (h *testSyncHooks) waitInactive() {
|
||||
for {
|
||||
<-h.inactive
|
||||
if !h.unlock() {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unlock releases the testSyncHooks mutex.
|
||||
// It reports whether any goroutines are active.
|
||||
func (h *testSyncHooks) unlock() (active bool) {
|
||||
// Look for a blocked goroutine which can be unblocked.
|
||||
blocked := h.blocked[:0]
|
||||
unblocked := false
|
||||
for _, b := range h.blocked {
|
||||
if !unblocked && b.f() {
|
||||
unblocked = true
|
||||
close(b.ch)
|
||||
} else {
|
||||
blocked = append(blocked, b)
|
||||
}
|
||||
}
|
||||
h.blocked = blocked
|
||||
|
||||
// Count goroutines blocked on condition variables.
|
||||
condwait := 0
|
||||
for _, count := range h.condwait {
|
||||
condwait += count
|
||||
}
|
||||
|
||||
if h.total > condwait+len(blocked) {
|
||||
h.active <- struct{}{}
|
||||
return true
|
||||
} else {
|
||||
h.inactive <- struct{}{}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// goRun starts a new goroutine.
|
||||
func (h *testSyncHooks) goRun(f func()) {
|
||||
h.lock()
|
||||
h.total++
|
||||
h.unlock()
|
||||
go func() {
|
||||
defer func() {
|
||||
h.lock()
|
||||
h.total--
|
||||
h.unlock()
|
||||
}()
|
||||
f()
|
||||
}()
|
||||
}
|
||||
|
||||
// blockUntil indicates that a goroutine is blocked waiting for some condition to become true.
|
||||
// It waits until f returns true before proceeding.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// h.blockUntil(func() bool {
|
||||
// // Is the context done yet?
|
||||
// select {
|
||||
// case <-ctx.Done():
|
||||
// default:
|
||||
// return false
|
||||
// }
|
||||
// return true
|
||||
// })
|
||||
// // Wait for the context to become done.
|
||||
// <-ctx.Done()
|
||||
//
|
||||
// The function f passed to blockUntil must be non-blocking and idempotent.
|
||||
func (h *testSyncHooks) blockUntil(f func() bool) {
|
||||
if f() {
|
||||
return
|
||||
}
|
||||
ch := make(chan struct{})
|
||||
h.lock()
|
||||
h.blocked = append(h.blocked, &testBlockedGoroutine{
|
||||
f: f,
|
||||
ch: ch,
|
||||
})
|
||||
h.unlock()
|
||||
<-ch
|
||||
}
|
||||
|
||||
// broadcast is sync.Cond.Broadcast.
|
||||
func (h *testSyncHooks) condBroadcast(cond *sync.Cond) {
|
||||
h.lock()
|
||||
delete(h.condwait, cond)
|
||||
h.unlock()
|
||||
cond.Broadcast()
|
||||
}
|
||||
|
||||
// broadcast is sync.Cond.Wait.
|
||||
func (h *testSyncHooks) condWait(cond *sync.Cond) {
|
||||
h.lock()
|
||||
h.condwait[cond]++
|
||||
h.unlock()
|
||||
}
|
||||
|
||||
// newTimer creates a new fake timer.
|
||||
func (h *testSyncHooks) newTimer(d time.Duration) timer {
|
||||
h.lock()
|
||||
defer h.unlock()
|
||||
t := &fakeTimer{
|
||||
hooks: h,
|
||||
when: h.now.Add(d),
|
||||
c: make(chan time.Time),
|
||||
}
|
||||
h.timers = append(h.timers, t)
|
||||
return t
|
||||
}
|
||||
|
||||
// afterFunc creates a new fake AfterFunc timer.
|
||||
func (h *testSyncHooks) afterFunc(d time.Duration, f func()) timer {
|
||||
h.lock()
|
||||
defer h.unlock()
|
||||
t := &fakeTimer{
|
||||
hooks: h,
|
||||
when: h.now.Add(d),
|
||||
f: f,
|
||||
}
|
||||
h.timers = append(h.timers, t)
|
||||
return t
|
||||
}
|
||||
|
||||
func (h *testSyncHooks) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
t := h.afterFunc(d, cancel)
|
||||
return ctx, func() {
|
||||
t.Stop()
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
|
||||
func (h *testSyncHooks) timeUntilEvent() time.Duration {
|
||||
h.lock()
|
||||
defer h.unlock()
|
||||
var next time.Time
|
||||
for _, t := range h.timers {
|
||||
if next.IsZero() || t.when.Before(next) {
|
||||
next = t.when
|
||||
}
|
||||
}
|
||||
if d := next.Sub(h.now); d > 0 {
|
||||
return d
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// advance advances time and causes synthetic timers to fire.
|
||||
func (h *testSyncHooks) advance(d time.Duration) {
|
||||
h.lock()
|
||||
defer h.unlock()
|
||||
h.now = h.now.Add(d)
|
||||
timers := h.timers[:0]
|
||||
for _, t := range h.timers {
|
||||
t := t // remove after go.mod depends on go1.22
|
||||
t.mu.Lock()
|
||||
switch {
|
||||
case t.when.After(h.now):
|
||||
timers = append(timers, t)
|
||||
case t.when.IsZero():
|
||||
// stopped timer
|
||||
default:
|
||||
t.when = time.Time{}
|
||||
if t.c != nil {
|
||||
close(t.c)
|
||||
}
|
||||
if t.f != nil {
|
||||
h.total++
|
||||
go func() {
|
||||
defer func() {
|
||||
h.lock()
|
||||
h.total--
|
||||
h.unlock()
|
||||
}()
|
||||
t.f()
|
||||
}()
|
||||
}
|
||||
}
|
||||
t.mu.Unlock()
|
||||
}
|
||||
h.timers = timers
|
||||
}
|
||||
|
||||
// A timer wraps a time.Timer, or a synthetic equivalent in tests.
|
||||
// Unlike time.Timer, timer is single-use: The timer channel is closed when the timer expires.
|
||||
type timer interface {
|
||||
C() <-chan time.Time
|
||||
Stop() bool
|
||||
Reset(d time.Duration) bool
|
||||
}
|
||||
|
||||
// timeTimer implements timer using real time.
|
||||
type timeTimer struct {
|
||||
t *time.Timer
|
||||
c chan time.Time
|
||||
}
|
||||
|
||||
// newTimeTimer creates a new timer using real time.
|
||||
func newTimeTimer(d time.Duration) timer {
|
||||
ch := make(chan time.Time)
|
||||
t := time.AfterFunc(d, func() {
|
||||
close(ch)
|
||||
})
|
||||
return &timeTimer{t, ch}
|
||||
}
|
||||
|
||||
// newTimeAfterFunc creates an AfterFunc timer using real time.
|
||||
func newTimeAfterFunc(d time.Duration, f func()) timer {
|
||||
return &timeTimer{
|
||||
t: time.AfterFunc(d, f),
|
||||
}
|
||||
}
|
||||
|
||||
func (t timeTimer) C() <-chan time.Time { return t.c }
|
||||
func (t timeTimer) Stop() bool { return t.t.Stop() }
|
||||
func (t timeTimer) Reset(d time.Duration) bool { return t.t.Reset(d) }
|
||||
|
||||
// fakeTimer implements timer using fake time.
|
||||
type fakeTimer struct {
|
||||
hooks *testSyncHooks
|
||||
|
||||
mu sync.Mutex
|
||||
when time.Time // when the timer will fire
|
||||
c chan time.Time // closed when the timer fires; mutually exclusive with f
|
||||
f func() // called when the timer fires; mutually exclusive with c
|
||||
}
|
||||
|
||||
func (t *fakeTimer) C() <-chan time.Time { return t.c }
|
||||
|
||||
func (t *fakeTimer) Stop() bool {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
stopped := t.when.IsZero()
|
||||
t.when = time.Time{}
|
||||
return stopped
|
||||
}
|
||||
|
||||
func (t *fakeTimer) Reset(d time.Duration) bool {
|
||||
if t.c != nil || t.f == nil {
|
||||
panic("fakeTimer only supports Reset on AfterFunc timers")
|
||||
}
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.hooks.lock()
|
||||
defer t.hooks.unlock()
|
||||
active := !t.when.IsZero()
|
||||
t.when = t.hooks.now.Add(d)
|
||||
if !active {
|
||||
t.hooks.timers = append(t.hooks.timers, t)
|
||||
}
|
||||
return active
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// Copyright 2024 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 http2
|
||||
|
||||
import "time"
|
||||
|
||||
// A timer is a time.Timer, as an interface which can be replaced in tests.
|
||||
type timer = interface {
|
||||
C() <-chan time.Time
|
||||
Reset(d time.Duration) bool
|
||||
Stop() bool
|
||||
}
|
||||
|
||||
// timeTimer adapts a time.Timer to the timer interface.
|
||||
type timeTimer struct {
|
||||
*time.Timer
|
||||
}
|
||||
|
||||
func (t timeTimer) C() <-chan time.Time { return t.Timer.C }
|
||||
+493
-625
File diff suppressed because it is too large.
Load diff
+32
@@ -0,0 +1,32 @@
|
||||
// Copyright 2024 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 http2
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
)
|
||||
|
||||
const nextProtoUnencryptedHTTP2 = "unencrypted_http2"
|
||||
|
||||
// unencryptedNetConnFromTLSConn retrieves a net.Conn wrapped in a *tls.Conn.
|
||||
//
|
||||
// TLSNextProto functions accept a *tls.Conn.
|
||||
//
|
||||
// When passing an unencrypted HTTP/2 connection to a TLSNextProto function,
|
||||
// we pass a *tls.Conn with an underlying net.Conn containing the unencrypted connection.
|
||||
// To be extra careful about mistakes (accidentally dropping TLS encryption in a place
|
||||
// where we want it), the tls.Conn contains a net.Conn with an UnencryptedNetConn method
|
||||
// that returns the actual connection we want to use.
|
||||
func unencryptedNetConnFromTLSConn(tc *tls.Conn) (net.Conn, error) {
|
||||
conner, ok := tc.NetConn().(interface {
|
||||
UnencryptedNetConn() net.Conn
|
||||
})
|
||||
if !ok {
|
||||
return nil, errors.New("http2: TLS conn unexpectedly found in unencrypted handoff")
|
||||
}
|
||||
return conner.UnencryptedNetConn(), nil
|
||||
}
|
||||
+12
-1
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"golang.org/x/net/http/httpguts"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"golang.org/x/net/internal/httpcommon"
|
||||
)
|
||||
|
||||
// writeFramer is implemented by any type that is used to write frames.
|
||||
@@ -131,6 +132,16 @@ func (se StreamError) writeFrame(ctx writeContext) error {
|
||||
|
||||
func (se StreamError) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max }
|
||||
|
||||
type writePing struct {
|
||||
data [8]byte
|
||||
}
|
||||
|
||||
func (w writePing) writeFrame(ctx writeContext) error {
|
||||
return ctx.Framer().WritePing(false, w.data)
|
||||
}
|
||||
|
||||
func (w writePing) staysWithinBuffer(max int) bool { return frameHeaderLen+len(w.data) <= max }
|
||||
|
||||
type writePingAck struct{ pf *PingFrame }
|
||||
|
||||
func (w writePingAck) writeFrame(ctx writeContext) error {
|
||||
@@ -341,7 +352,7 @@ func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
|
||||
}
|
||||
for _, k := range keys {
|
||||
vv := h[k]
|
||||
k, ascii := lowerHeader(k)
|
||||
k, ascii := httpcommon.LowerHeader(k)
|
||||
if !ascii {
|
||||
// Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
|
||||
// field names have to be ASCII characters (just as in HTTP/1.x).
|
||||
|
||||
+2
-2
@@ -443,8 +443,8 @@ func (ws *priorityWriteScheduler) addClosedOrIdleNode(list *[]*priorityNode, max
|
||||
}
|
||||
|
||||
func (ws *priorityWriteScheduler) removeNode(n *priorityNode) {
|
||||
for k := n.kids; k != nil; k = k.next {
|
||||
k.setParent(n.parent)
|
||||
for n.kids != nil {
|
||||
n.kids.setParent(n.parent)
|
||||
}
|
||||
n.setParent(nil)
|
||||
delete(ws.nodes, n.id)
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// Copyright 2025 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 httpcommon
|
||||
|
||||
import "strings"
|
||||
|
||||
// The HTTP protocols are defined in terms of ASCII, not Unicode. This file
|
||||
// contains helper functions which may use Unicode-aware functions which would
|
||||
// otherwise be unsafe and could introduce vulnerabilities if used improperly.
|
||||
|
||||
// asciiEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
|
||||
// are equal, ASCII-case-insensitively.
|
||||
func asciiEqualFold(s, t string) bool {
|
||||
if len(s) != len(t) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(s); i++ {
|
||||
if lower(s[i]) != lower(t[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// lower returns the ASCII lowercase version of b.
|
||||
func lower(b byte) byte {
|
||||
if 'A' <= b && b <= 'Z' {
|
||||
return b + ('a' - 'A')
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// isASCIIPrint returns whether s is ASCII and printable according to
|
||||
// https://tools.ietf.org/html/rfc20#section-4.2.
|
||||
func isASCIIPrint(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] < ' ' || s[i] > '~' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// asciiToLower returns the lowercase version of s if s is ASCII and printable,
|
||||
// and whether or not it was.
|
||||
func asciiToLower(s string) (lower string, ok bool) {
|
||||
if !isASCIIPrint(s) {
|
||||
return "", false
|
||||
}
|
||||
return strings.ToLower(s), true
|
||||
}
|
||||
Generated
Vendored
+17
-7
@@ -1,11 +1,11 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Copyright 2025 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 http2
|
||||
package httpcommon
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -82,13 +82,15 @@ func buildCommonHeaderMaps() {
|
||||
commonLowerHeader = make(map[string]string, len(common))
|
||||
commonCanonHeader = make(map[string]string, len(common))
|
||||
for _, v := range common {
|
||||
chk := http.CanonicalHeaderKey(v)
|
||||
chk := textproto.CanonicalMIMEHeaderKey(v)
|
||||
commonLowerHeader[chk] = v
|
||||
commonCanonHeader[v] = chk
|
||||
}
|
||||
}
|
||||
|
||||
func lowerHeader(v string) (lower string, ascii bool) {
|
||||
// LowerHeader returns the lowercase form of a header name,
|
||||
// used on the wire for HTTP/2 and HTTP/3 requests.
|
||||
func LowerHeader(v string) (lower string, ascii bool) {
|
||||
buildCommonHeaderMapsOnce()
|
||||
if s, ok := commonLowerHeader[v]; ok {
|
||||
return s, true
|
||||
@@ -96,10 +98,18 @@ func lowerHeader(v string) (lower string, ascii bool) {
|
||||
return asciiToLower(v)
|
||||
}
|
||||
|
||||
func canonicalHeader(v string) string {
|
||||
// CanonicalHeader canonicalizes a header name. (For example, "host" becomes "Host".)
|
||||
func CanonicalHeader(v string) string {
|
||||
buildCommonHeaderMapsOnce()
|
||||
if s, ok := commonCanonHeader[v]; ok {
|
||||
return s
|
||||
}
|
||||
return http.CanonicalHeaderKey(v)
|
||||
return textproto.CanonicalMIMEHeaderKey(v)
|
||||
}
|
||||
|
||||
// CachedCanonicalHeader returns the canonical form of a well-known header name.
|
||||
func CachedCanonicalHeader(v string) (string, bool) {
|
||||
buildCommonHeaderMapsOnce()
|
||||
s, ok := commonCanonHeader[v]
|
||||
return s, ok
|
||||
}
|
||||
+467
@@ -0,0 +1,467 @@
|
||||
// Copyright 2025 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 httpcommon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http/httptrace"
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/http/httpguts"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrRequestHeaderListSize = errors.New("request header list larger than peer's advertised limit")
|
||||
)
|
||||
|
||||
// Request is a subset of http.Request.
|
||||
// It'd be simpler to pass an *http.Request, of course, but we can't depend on net/http
|
||||
// without creating a dependency cycle.
|
||||
type Request struct {
|
||||
URL *url.URL
|
||||
Method string
|
||||
Host string
|
||||
Header map[string][]string
|
||||
Trailer map[string][]string
|
||||
ActualContentLength int64 // 0 means 0, -1 means unknown
|
||||
}
|
||||
|
||||
// EncodeHeadersParam is parameters to EncodeHeaders.
|
||||
type EncodeHeadersParam struct {
|
||||
Request Request
|
||||
|
||||
// AddGzipHeader indicates that an "accept-encoding: gzip" header should be
|
||||
// added to the request.
|
||||
AddGzipHeader bool
|
||||
|
||||
// PeerMaxHeaderListSize, when non-zero, is the peer's MAX_HEADER_LIST_SIZE setting.
|
||||
PeerMaxHeaderListSize uint64
|
||||
|
||||
// DefaultUserAgent is the User-Agent header to send when the request
|
||||
// neither contains a User-Agent nor disables it.
|
||||
DefaultUserAgent string
|
||||
}
|
||||
|
||||
// EncodeHeadersParam is the result of EncodeHeaders.
|
||||
type EncodeHeadersResult struct {
|
||||
HasBody bool
|
||||
HasTrailers bool
|
||||
}
|
||||
|
||||
// EncodeHeaders constructs request headers common to HTTP/2 and HTTP/3.
|
||||
// It validates a request and calls headerf with each pseudo-header and header
|
||||
// for the request.
|
||||
// The headerf function is called with the validated, canonicalized header name.
|
||||
func EncodeHeaders(ctx context.Context, param EncodeHeadersParam, headerf func(name, value string)) (res EncodeHeadersResult, _ error) {
|
||||
req := param.Request
|
||||
|
||||
// Check for invalid connection-level headers.
|
||||
if err := checkConnHeaders(req.Header); err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if req.URL == nil {
|
||||
return res, errors.New("Request.URL is nil")
|
||||
}
|
||||
|
||||
host := req.Host
|
||||
if host == "" {
|
||||
host = req.URL.Host
|
||||
}
|
||||
host, err := httpguts.PunycodeHostPort(host)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if !httpguts.ValidHostHeader(host) {
|
||||
return res, errors.New("invalid Host header")
|
||||
}
|
||||
|
||||
// isNormalConnect is true if this is a non-extended CONNECT request.
|
||||
isNormalConnect := false
|
||||
var protocol string
|
||||
if vv := req.Header[":protocol"]; len(vv) > 0 {
|
||||
protocol = vv[0]
|
||||
}
|
||||
if req.Method == "CONNECT" && protocol == "" {
|
||||
isNormalConnect = true
|
||||
} else if protocol != "" && req.Method != "CONNECT" {
|
||||
return res, errors.New("invalid :protocol header in non-CONNECT request")
|
||||
}
|
||||
|
||||
// Validate the path, except for non-extended CONNECT requests which have no path.
|
||||
var path string
|
||||
if !isNormalConnect {
|
||||
path = req.URL.RequestURI()
|
||||
if !validPseudoPath(path) {
|
||||
orig := path
|
||||
path = strings.TrimPrefix(path, req.URL.Scheme+"://"+host)
|
||||
if !validPseudoPath(path) {
|
||||
if req.URL.Opaque != "" {
|
||||
return res, fmt.Errorf("invalid request :path %q from URL.Opaque = %q", orig, req.URL.Opaque)
|
||||
} else {
|
||||
return res, fmt.Errorf("invalid request :path %q", orig)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for any invalid headers+trailers and return an error before we
|
||||
// potentially pollute our hpack state. (We want to be able to
|
||||
// continue to reuse the hpack encoder for future requests)
|
||||
if err := validateHeaders(req.Header); err != "" {
|
||||
return res, fmt.Errorf("invalid HTTP header %s", err)
|
||||
}
|
||||
if err := validateHeaders(req.Trailer); err != "" {
|
||||
return res, fmt.Errorf("invalid HTTP trailer %s", err)
|
||||
}
|
||||
|
||||
trailers, err := commaSeparatedTrailers(req.Trailer)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
enumerateHeaders := func(f func(name, value string)) {
|
||||
// 8.1.2.3 Request Pseudo-Header Fields
|
||||
// The :path pseudo-header field includes the path and query parts of the
|
||||
// target URI (the path-absolute production and optionally a '?' character
|
||||
// followed by the query production, see Sections 3.3 and 3.4 of
|
||||
// [RFC3986]).
|
||||
f(":authority", host)
|
||||
m := req.Method
|
||||
if m == "" {
|
||||
m = "GET"
|
||||
}
|
||||
f(":method", m)
|
||||
if !isNormalConnect {
|
||||
f(":path", path)
|
||||
f(":scheme", req.URL.Scheme)
|
||||
}
|
||||
if protocol != "" {
|
||||
f(":protocol", protocol)
|
||||
}
|
||||
if trailers != "" {
|
||||
f("trailer", trailers)
|
||||
}
|
||||
|
||||
var didUA bool
|
||||
for k, vv := range req.Header {
|
||||
if asciiEqualFold(k, "host") || asciiEqualFold(k, "content-length") {
|
||||
// Host is :authority, already sent.
|
||||
// Content-Length is automatic, set below.
|
||||
continue
|
||||
} else if asciiEqualFold(k, "connection") ||
|
||||
asciiEqualFold(k, "proxy-connection") ||
|
||||
asciiEqualFold(k, "transfer-encoding") ||
|
||||
asciiEqualFold(k, "upgrade") ||
|
||||
asciiEqualFold(k, "keep-alive") {
|
||||
// Per 8.1.2.2 Connection-Specific Header
|
||||
// Fields, don't send connection-specific
|
||||
// fields. We have already checked if any
|
||||
// are error-worthy so just ignore the rest.
|
||||
continue
|
||||
} else if asciiEqualFold(k, "user-agent") {
|
||||
// Match Go's http1 behavior: at most one
|
||||
// User-Agent. If set to nil or empty string,
|
||||
// then omit it. Otherwise if not mentioned,
|
||||
// include the default (below).
|
||||
didUA = true
|
||||
if len(vv) < 1 {
|
||||
continue
|
||||
}
|
||||
vv = vv[:1]
|
||||
if vv[0] == "" {
|
||||
continue
|
||||
}
|
||||
} else if asciiEqualFold(k, "cookie") {
|
||||
// Per 8.1.2.5 To allow for better compression efficiency, the
|
||||
// Cookie header field MAY be split into separate header fields,
|
||||
// each with one or more cookie-pairs.
|
||||
for _, v := range vv {
|
||||
for {
|
||||
p := strings.IndexByte(v, ';')
|
||||
if p < 0 {
|
||||
break
|
||||
}
|
||||
f("cookie", v[:p])
|
||||
p++
|
||||
// strip space after semicolon if any.
|
||||
for p+1 <= len(v) && v[p] == ' ' {
|
||||
p++
|
||||
}
|
||||
v = v[p:]
|
||||
}
|
||||
if len(v) > 0 {
|
||||
f("cookie", v)
|
||||
}
|
||||
}
|
||||
continue
|
||||
} else if k == ":protocol" {
|
||||
// :protocol pseudo-header was already sent above.
|
||||
continue
|
||||
}
|
||||
|
||||
for _, v := range vv {
|
||||
f(k, v)
|
||||
}
|
||||
}
|
||||
if shouldSendReqContentLength(req.Method, req.ActualContentLength) {
|
||||
f("content-length", strconv.FormatInt(req.ActualContentLength, 10))
|
||||
}
|
||||
if param.AddGzipHeader {
|
||||
f("accept-encoding", "gzip")
|
||||
}
|
||||
if !didUA {
|
||||
f("user-agent", param.DefaultUserAgent)
|
||||
}
|
||||
}
|
||||
|
||||
// Do a first pass over the headers counting bytes to ensure
|
||||
// we don't exceed cc.peerMaxHeaderListSize. This is done as a
|
||||
// separate pass before encoding the headers to prevent
|
||||
// modifying the hpack state.
|
||||
if param.PeerMaxHeaderListSize > 0 {
|
||||
hlSize := uint64(0)
|
||||
enumerateHeaders(func(name, value string) {
|
||||
hf := hpack.HeaderField{Name: name, Value: value}
|
||||
hlSize += uint64(hf.Size())
|
||||
})
|
||||
|
||||
if hlSize > param.PeerMaxHeaderListSize {
|
||||
return res, ErrRequestHeaderListSize
|
||||
}
|
||||
}
|
||||
|
||||
trace := httptrace.ContextClientTrace(ctx)
|
||||
|
||||
// Header list size is ok. Write the headers.
|
||||
enumerateHeaders(func(name, value string) {
|
||||
name, ascii := LowerHeader(name)
|
||||
if !ascii {
|
||||
// Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
|
||||
// field names have to be ASCII characters (just as in HTTP/1.x).
|
||||
return
|
||||
}
|
||||
|
||||
headerf(name, value)
|
||||
|
||||
if trace != nil && trace.WroteHeaderField != nil {
|
||||
trace.WroteHeaderField(name, []string{value})
|
||||
}
|
||||
})
|
||||
|
||||
res.HasBody = req.ActualContentLength != 0
|
||||
res.HasTrailers = trailers != ""
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// IsRequestGzip reports whether we should add an Accept-Encoding: gzip header
|
||||
// for a request.
|
||||
func IsRequestGzip(method string, header map[string][]string, disableCompression bool) bool {
|
||||
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
|
||||
if !disableCompression &&
|
||||
len(header["Accept-Encoding"]) == 0 &&
|
||||
len(header["Range"]) == 0 &&
|
||||
method != "HEAD" {
|
||||
// Request gzip only, not deflate. Deflate is ambiguous and
|
||||
// not as universally supported anyway.
|
||||
// See: https://zlib.net/zlib_faq.html#faq39
|
||||
//
|
||||
// Note that we don't request this for HEAD requests,
|
||||
// due to a bug in nginx:
|
||||
// http://trac.nginx.org/nginx/ticket/358
|
||||
// https://golang.org/issue/5522
|
||||
//
|
||||
// We don't request gzip if the request is for a range, since
|
||||
// auto-decoding a portion of a gzipped document will just fail
|
||||
// anyway. See https://golang.org/issue/8923
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// checkConnHeaders checks whether req has any invalid connection-level headers.
|
||||
//
|
||||
// https://www.rfc-editor.org/rfc/rfc9114.html#section-4.2-3
|
||||
// https://www.rfc-editor.org/rfc/rfc9113.html#section-8.2.2-1
|
||||
//
|
||||
// Certain headers are special-cased as okay but not transmitted later.
|
||||
// For example, we allow "Transfer-Encoding: chunked", but drop the header when encoding.
|
||||
func checkConnHeaders(h map[string][]string) error {
|
||||
if vv := h["Upgrade"]; len(vv) > 0 && (vv[0] != "" && vv[0] != "chunked") {
|
||||
return fmt.Errorf("invalid Upgrade request header: %q", vv)
|
||||
}
|
||||
if vv := h["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") {
|
||||
return fmt.Errorf("invalid Transfer-Encoding request header: %q", vv)
|
||||
}
|
||||
if vv := h["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !asciiEqualFold(vv[0], "close") && !asciiEqualFold(vv[0], "keep-alive")) {
|
||||
return fmt.Errorf("invalid Connection request header: %q", vv)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func commaSeparatedTrailers(trailer map[string][]string) (string, error) {
|
||||
keys := make([]string, 0, len(trailer))
|
||||
for k := range trailer {
|
||||
k = CanonicalHeader(k)
|
||||
switch k {
|
||||
case "Transfer-Encoding", "Trailer", "Content-Length":
|
||||
return "", fmt.Errorf("invalid Trailer key %q", k)
|
||||
}
|
||||
keys = append(keys, k)
|
||||
}
|
||||
if len(keys) > 0 {
|
||||
sort.Strings(keys)
|
||||
return strings.Join(keys, ","), nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// validPseudoPath reports whether v is a valid :path pseudo-header
|
||||
// value. It must be either:
|
||||
//
|
||||
// - a non-empty string starting with '/'
|
||||
// - the string '*', for OPTIONS requests.
|
||||
//
|
||||
// For now this is only used a quick check for deciding when to clean
|
||||
// up Opaque URLs before sending requests from the Transport.
|
||||
// See golang.org/issue/16847
|
||||
//
|
||||
// We used to enforce that the path also didn't start with "//", but
|
||||
// Google's GFE accepts such paths and Chrome sends them, so ignore
|
||||
// that part of the spec. See golang.org/issue/19103.
|
||||
func validPseudoPath(v string) bool {
|
||||
return (len(v) > 0 && v[0] == '/') || v == "*"
|
||||
}
|
||||
|
||||
func validateHeaders(hdrs map[string][]string) string {
|
||||
for k, vv := range hdrs {
|
||||
if !httpguts.ValidHeaderFieldName(k) && k != ":protocol" {
|
||||
return fmt.Sprintf("name %q", k)
|
||||
}
|
||||
for _, v := range vv {
|
||||
if !httpguts.ValidHeaderFieldValue(v) {
|
||||
// Don't include the value in the error,
|
||||
// because it may be sensitive.
|
||||
return fmt.Sprintf("value for header %q", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// shouldSendReqContentLength reports whether we should send
|
||||
// a "content-length" request header. This logic is basically a copy of the net/http
|
||||
// transferWriter.shouldSendContentLength.
|
||||
// The contentLength is the corrected contentLength (so 0 means actually 0, not unknown).
|
||||
// -1 means unknown.
|
||||
func shouldSendReqContentLength(method string, contentLength int64) bool {
|
||||
if contentLength > 0 {
|
||||
return true
|
||||
}
|
||||
if contentLength < 0 {
|
||||
return false
|
||||
}
|
||||
// For zero bodies, whether we send a content-length depends on the method.
|
||||
// It also kinda doesn't matter for http2 either way, with END_STREAM.
|
||||
switch method {
|
||||
case "POST", "PUT", "PATCH":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// ServerRequestParam is parameters to NewServerRequest.
|
||||
type ServerRequestParam struct {
|
||||
Method string
|
||||
Scheme, Authority, Path string
|
||||
Protocol string
|
||||
Header map[string][]string
|
||||
}
|
||||
|
||||
// ServerRequestResult is the result of NewServerRequest.
|
||||
type ServerRequestResult struct {
|
||||
// Various http.Request fields.
|
||||
URL *url.URL
|
||||
RequestURI string
|
||||
Trailer map[string][]string
|
||||
|
||||
NeedsContinue bool // client provided an "Expect: 100-continue" header
|
||||
|
||||
// If the request should be rejected, this is a short string suitable for passing
|
||||
// to the http2 package's CountError function.
|
||||
// It might be a bit odd to return errors this way rather than returing an error,
|
||||
// but this ensures we don't forget to include a CountError reason.
|
||||
InvalidReason string
|
||||
}
|
||||
|
||||
func NewServerRequest(rp ServerRequestParam) ServerRequestResult {
|
||||
needsContinue := httpguts.HeaderValuesContainsToken(rp.Header["Expect"], "100-continue")
|
||||
if needsContinue {
|
||||
delete(rp.Header, "Expect")
|
||||
}
|
||||
// Merge Cookie headers into one "; "-delimited value.
|
||||
if cookies := rp.Header["Cookie"]; len(cookies) > 1 {
|
||||
rp.Header["Cookie"] = []string{strings.Join(cookies, "; ")}
|
||||
}
|
||||
|
||||
// Setup Trailers
|
||||
var trailer map[string][]string
|
||||
for _, v := range rp.Header["Trailer"] {
|
||||
for _, key := range strings.Split(v, ",") {
|
||||
key = textproto.CanonicalMIMEHeaderKey(textproto.TrimString(key))
|
||||
switch key {
|
||||
case "Transfer-Encoding", "Trailer", "Content-Length":
|
||||
// Bogus. (copy of http1 rules)
|
||||
// Ignore.
|
||||
default:
|
||||
if trailer == nil {
|
||||
trailer = make(map[string][]string)
|
||||
}
|
||||
trailer[key] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
delete(rp.Header, "Trailer")
|
||||
|
||||
// "':authority' MUST NOT include the deprecated userinfo subcomponent
|
||||
// for "http" or "https" schemed URIs."
|
||||
// https://www.rfc-editor.org/rfc/rfc9113.html#section-8.3.1-2.3.8
|
||||
if strings.IndexByte(rp.Authority, '@') != -1 && (rp.Scheme == "http" || rp.Scheme == "https") {
|
||||
return ServerRequestResult{
|
||||
InvalidReason: "userinfo_in_authority",
|
||||
}
|
||||
}
|
||||
|
||||
var url_ *url.URL
|
||||
var requestURI string
|
||||
if rp.Method == "CONNECT" && rp.Protocol == "" {
|
||||
url_ = &url.URL{Host: rp.Authority}
|
||||
requestURI = rp.Authority // mimic HTTP/1 server behavior
|
||||
} else {
|
||||
var err error
|
||||
url_, err = url.ParseRequestURI(rp.Path)
|
||||
if err != nil {
|
||||
return ServerRequestResult{
|
||||
InvalidReason: "bad_path",
|
||||
}
|
||||
}
|
||||
requestURI = rp.Path
|
||||
}
|
||||
|
||||
return ServerRequestResult{
|
||||
URL: url_,
|
||||
NeedsContinue: needsContinue,
|
||||
RequestURI: requestURI,
|
||||
Trailer: trailer,
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -508,7 +508,7 @@ const eventsHTML = `
|
||||
<tr class="first">
|
||||
<td class="when">{{$el.When}}</td>
|
||||
<td class="elapsed">{{$el.ElapsedTime}}</td>
|
||||
<td>{{$el.Title}}
|
||||
<td>{{$el.Title}}</td>
|
||||
</tr>
|
||||
{{if $.Expanded}}
|
||||
<tr>
|
||||
|
||||
+2
-3
@@ -16,7 +16,6 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -279,7 +278,7 @@ func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (frameReader, er
|
||||
}
|
||||
}
|
||||
if header := frame.HeaderReader(); header != nil {
|
||||
io.Copy(ioutil.Discard, header)
|
||||
io.Copy(io.Discard, header)
|
||||
}
|
||||
switch frame.PayloadType() {
|
||||
case ContinuationFrame:
|
||||
@@ -294,7 +293,7 @@ func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (frameReader, er
|
||||
if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
|
||||
return nil, err
|
||||
}
|
||||
io.Copy(ioutil.Discard, frame)
|
||||
io.Copy(io.Discard, frame)
|
||||
if frame.PayloadType() == PingFrame {
|
||||
if _, err := handler.WritePong(b[:n]); err != nil {
|
||||
return nil, err
|
||||
|
||||
+6
-6
@@ -6,9 +6,10 @@
|
||||
// as specified in RFC 6455.
|
||||
//
|
||||
// This package currently lacks some features found in an alternative
|
||||
// and more actively maintained WebSocket package:
|
||||
// and more actively maintained WebSocket packages:
|
||||
//
|
||||
// https://pkg.go.dev/nhooyr.io/websocket
|
||||
// - [github.com/gorilla/websocket]
|
||||
// - [github.com/coder/websocket]
|
||||
package websocket // import "golang.org/x/net/websocket"
|
||||
|
||||
import (
|
||||
@@ -17,7 +18,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -208,7 +208,7 @@ again:
|
||||
n, err = ws.frameReader.Read(msg)
|
||||
if err == io.EOF {
|
||||
if trailer := ws.frameReader.TrailerReader(); trailer != nil {
|
||||
io.Copy(ioutil.Discard, trailer)
|
||||
io.Copy(io.Discard, trailer)
|
||||
}
|
||||
ws.frameReader = nil
|
||||
goto again
|
||||
@@ -330,7 +330,7 @@ func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
|
||||
ws.rio.Lock()
|
||||
defer ws.rio.Unlock()
|
||||
if ws.frameReader != nil {
|
||||
_, err = io.Copy(ioutil.Discard, ws.frameReader)
|
||||
_, err = io.Copy(io.Discard, ws.frameReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -362,7 +362,7 @@ again:
|
||||
return ErrFrameTooLarge
|
||||
}
|
||||
payloadType := frame.PayloadType()
|
||||
data, err := ioutil.ReadAll(frame)
|
||||
data, err := io.ReadAll(frame)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
Copyright 2009 The Go Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
|
||||
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
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
|
||||
+5
-10
@@ -5,15 +5,6 @@
|
||||
|
||||
oauth2 package contains a client implementation for OAuth 2.0 spec.
|
||||
|
||||
## Installation
|
||||
|
||||
~~~~
|
||||
go get golang.org/x/oauth2
|
||||
~~~~
|
||||
|
||||
Or you can manually git clone the repository to
|
||||
`$(go env GOPATH)/src/golang.org/x/oauth2`.
|
||||
|
||||
See pkg.go.dev for further documentation and examples.
|
||||
|
||||
* [pkg.go.dev/golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2)
|
||||
@@ -33,7 +24,11 @@ The main issue tracker for the oauth2 repository is located at
|
||||
https://github.com/golang/oauth2/issues.
|
||||
|
||||
This repository uses Gerrit for code changes. To learn how to submit changes to
|
||||
this repository, see https://golang.org/doc/contribute.html. In particular:
|
||||
this repository, see https://go.dev/doc/contribute.
|
||||
|
||||
The git repository is https://go.googlesource.com/oauth2.
|
||||
|
||||
Note:
|
||||
|
||||
* Excluding trivial changes, all contributions should be connected to an existing issue.
|
||||
* API changes must go through the [change proposal process](https://go.dev/s/proposal-process) before they can be accepted.
|
||||
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
package oauth2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2/internal"
|
||||
)
|
||||
|
||||
// https://datatracker.ietf.org/doc/html/rfc8628#section-3.5
|
||||
const (
|
||||
errAuthorizationPending = "authorization_pending"
|
||||
errSlowDown = "slow_down"
|
||||
errAccessDenied = "access_denied"
|
||||
errExpiredToken = "expired_token"
|
||||
)
|
||||
|
||||
// DeviceAuthResponse describes a successful RFC 8628 Device Authorization Response
|
||||
// https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
|
||||
type DeviceAuthResponse struct {
|
||||
// DeviceCode
|
||||
DeviceCode string `json:"device_code"`
|
||||
// UserCode is the code the user should enter at the verification uri
|
||||
UserCode string `json:"user_code"`
|
||||
// VerificationURI is where user should enter the user code
|
||||
VerificationURI string `json:"verification_uri"`
|
||||
// VerificationURIComplete (if populated) includes the user code in the verification URI. This is typically shown to the user in non-textual form, such as a QR code.
|
||||
VerificationURIComplete string `json:"verification_uri_complete,omitempty"`
|
||||
// Expiry is when the device code and user code expire
|
||||
Expiry time.Time `json:"expires_in,omitempty"`
|
||||
// Interval is the duration in seconds that Poll should wait between requests
|
||||
Interval int64 `json:"interval,omitempty"`
|
||||
}
|
||||
|
||||
func (d DeviceAuthResponse) MarshalJSON() ([]byte, error) {
|
||||
type Alias DeviceAuthResponse
|
||||
var expiresIn int64
|
||||
if !d.Expiry.IsZero() {
|
||||
expiresIn = int64(time.Until(d.Expiry).Seconds())
|
||||
}
|
||||
return json.Marshal(&struct {
|
||||
ExpiresIn int64 `json:"expires_in,omitempty"`
|
||||
*Alias
|
||||
}{
|
||||
ExpiresIn: expiresIn,
|
||||
Alias: (*Alias)(&d),
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (c *DeviceAuthResponse) UnmarshalJSON(data []byte) error {
|
||||
type Alias DeviceAuthResponse
|
||||
aux := &struct {
|
||||
ExpiresIn int64 `json:"expires_in"`
|
||||
// workaround misspelling of verification_uri
|
||||
VerificationURL string `json:"verification_url"`
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(c),
|
||||
}
|
||||
if err := json.Unmarshal(data, &aux); err != nil {
|
||||
return err
|
||||
}
|
||||
if aux.ExpiresIn != 0 {
|
||||
c.Expiry = time.Now().UTC().Add(time.Second * time.Duration(aux.ExpiresIn))
|
||||
}
|
||||
if c.VerificationURI == "" {
|
||||
c.VerificationURI = aux.VerificationURL
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeviceAuth returns a device auth struct which contains a device code
|
||||
// and authorization information provided for users to enter on another device.
|
||||
func (c *Config) DeviceAuth(ctx context.Context, opts ...AuthCodeOption) (*DeviceAuthResponse, error) {
|
||||
// https://datatracker.ietf.org/doc/html/rfc8628#section-3.1
|
||||
v := url.Values{
|
||||
"client_id": {c.ClientID},
|
||||
}
|
||||
if len(c.Scopes) > 0 {
|
||||
v.Set("scope", strings.Join(c.Scopes, " "))
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt.setValue(v)
|
||||
}
|
||||
return retrieveDeviceAuth(ctx, c, v)
|
||||
}
|
||||
|
||||
func retrieveDeviceAuth(ctx context.Context, c *Config, v url.Values) (*DeviceAuthResponse, error) {
|
||||
if c.Endpoint.DeviceAuthURL == "" {
|
||||
return nil, errors.New("endpoint missing DeviceAuthURL")
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", c.Endpoint.DeviceAuthURL, strings.NewReader(v.Encode()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
t := time.Now()
|
||||
r, err := internal.ContextClient(ctx).Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("oauth2: cannot auth device: %v", err)
|
||||
}
|
||||
if code := r.StatusCode; code < 200 || code > 299 {
|
||||
return nil, &RetrieveError{
|
||||
Response: r,
|
||||
Body: body,
|
||||
}
|
||||
}
|
||||
|
||||
da := &DeviceAuthResponse{}
|
||||
err = json.Unmarshal(body, &da)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unmarshal %s", err)
|
||||
}
|
||||
|
||||
if !da.Expiry.IsZero() {
|
||||
// Make a small adjustment to account for time taken by the request
|
||||
da.Expiry = da.Expiry.Add(-time.Since(t))
|
||||
}
|
||||
|
||||
return da, nil
|
||||
}
|
||||
|
||||
// DeviceAccessToken polls the server to exchange a device code for a token.
|
||||
func (c *Config) DeviceAccessToken(ctx context.Context, da *DeviceAuthResponse, opts ...AuthCodeOption) (*Token, error) {
|
||||
if !da.Expiry.IsZero() {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithDeadline(ctx, da.Expiry)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
// https://datatracker.ietf.org/doc/html/rfc8628#section-3.4
|
||||
v := url.Values{
|
||||
"client_id": {c.ClientID},
|
||||
"grant_type": {"urn:ietf:params:oauth:grant-type:device_code"},
|
||||
"device_code": {da.DeviceCode},
|
||||
}
|
||||
if len(c.Scopes) > 0 {
|
||||
v.Set("scope", strings.Join(c.Scopes, " "))
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt.setValue(v)
|
||||
}
|
||||
|
||||
// "If no value is provided, clients MUST use 5 as the default."
|
||||
// https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
|
||||
interval := da.Interval
|
||||
if interval == 0 {
|
||||
interval = 5
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(time.Duration(interval) * time.Second)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
case <-ticker.C:
|
||||
tok, err := retrieveToken(ctx, c, v)
|
||||
if err == nil {
|
||||
return tok, nil
|
||||
}
|
||||
|
||||
e, ok := err.(*RetrieveError)
|
||||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
switch e.ErrorCode {
|
||||
case errSlowDown:
|
||||
// https://datatracker.ietf.org/doc/html/rfc8628#section-3.5
|
||||
// "the interval MUST be increased by 5 seconds for this and all subsequent requests"
|
||||
interval += 5
|
||||
ticker.Reset(time.Duration(interval) * time.Second)
|
||||
case errAuthorizationPending:
|
||||
// Do nothing.
|
||||
case errAccessDenied, errExpiredToken:
|
||||
fallthrough
|
||||
default:
|
||||
return tok, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
// 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 appengine
|
||||
|
||||
package internal
|
||||
|
||||
import "google.golang.org/appengine/urlfetch"
|
||||
|
||||
func init() {
|
||||
appengineClientHook = urlfetch.Client
|
||||
}
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package internal contains support packages for oauth2 package.
|
||||
// Package internal contains support packages for [golang.org/x/oauth2].
|
||||
package internal
|
||||
+1
-1
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// ParseKey converts the binary contents of a private key file
|
||||
// to an *rsa.PrivateKey. It detects whether the private key is in a
|
||||
// to an [*rsa.PrivateKey]. It detects whether the private key is in a
|
||||
// PEM container or not. If so, it extracts the private key
|
||||
// from PEM container before conversion. It only supports PEM
|
||||
// containers with no passphrase.
|
||||
|
||||
+64
-40
@@ -10,7 +10,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"mime"
|
||||
"net/http"
|
||||
@@ -18,6 +17,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -25,9 +25,9 @@ import (
|
||||
// the requests to access protected resources on the OAuth 2.0
|
||||
// provider's backend.
|
||||
//
|
||||
// This type is a mirror of oauth2.Token and exists to break
|
||||
// This type is a mirror of [golang.org/x/oauth2.Token] and exists to break
|
||||
// an otherwise-circular dependency. Other internal packages
|
||||
// should convert this Token into an oauth2.Token before use.
|
||||
// should convert this Token into an [golang.org/x/oauth2.Token] before use.
|
||||
type Token struct {
|
||||
// AccessToken is the token that authorizes and authenticates
|
||||
// the requests.
|
||||
@@ -49,9 +49,16 @@ type Token struct {
|
||||
// mechanisms for that TokenSource will not be used.
|
||||
Expiry time.Time
|
||||
|
||||
// ExpiresIn is the OAuth2 wire format "expires_in" field,
|
||||
// which specifies how many seconds later the token expires,
|
||||
// relative to an unknown time base approximately around "now".
|
||||
// It is the application's responsibility to populate
|
||||
// `Expiry` from `ExpiresIn` when required.
|
||||
ExpiresIn int64 `json:"expires_in,omitempty"`
|
||||
|
||||
// Raw optionally contains extra metadata from the server
|
||||
// when updating a token.
|
||||
Raw interface{}
|
||||
Raw any
|
||||
}
|
||||
|
||||
// tokenJSON is the struct representing the HTTP response from OAuth2
|
||||
@@ -98,14 +105,6 @@ func (e *expirationTime) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op.
|
||||
//
|
||||
// Deprecated: this function no longer does anything. Caller code that
|
||||
// wants to avoid potential extra HTTP requests made during
|
||||
// auto-probing of the provider's auth style should set
|
||||
// Endpoint.AuthStyle.
|
||||
func RegisterBrokenAuthHeaderProvider(tokenURL string) {}
|
||||
|
||||
// AuthStyle is a copy of the golang.org/x/oauth2 package's AuthStyle type.
|
||||
type AuthStyle int
|
||||
|
||||
@@ -115,41 +114,65 @@ const (
|
||||
AuthStyleInHeader AuthStyle = 2
|
||||
)
|
||||
|
||||
// authStyleCache is the set of tokenURLs we've successfully used via
|
||||
// LazyAuthStyleCache is a backwards compatibility compromise to let Configs
|
||||
// have a lazily-initialized AuthStyleCache.
|
||||
//
|
||||
// The two users of this, oauth2.Config and oauth2/clientcredentials.Config,
|
||||
// both would ideally just embed an unexported AuthStyleCache but because both
|
||||
// were historically allowed to be copied by value we can't retroactively add an
|
||||
// uncopyable Mutex to them.
|
||||
//
|
||||
// We could use an atomic.Pointer, but that was added recently enough (in Go
|
||||
// 1.18) that we'd break Go 1.17 users where the tests as of 2023-08-03
|
||||
// still pass. By using an atomic.Value, it supports both Go 1.17 and
|
||||
// copying by value, even if that's not ideal.
|
||||
type LazyAuthStyleCache struct {
|
||||
v atomic.Value // of *AuthStyleCache
|
||||
}
|
||||
|
||||
func (lc *LazyAuthStyleCache) Get() *AuthStyleCache {
|
||||
if c, ok := lc.v.Load().(*AuthStyleCache); ok {
|
||||
return c
|
||||
}
|
||||
c := new(AuthStyleCache)
|
||||
if !lc.v.CompareAndSwap(nil, c) {
|
||||
c = lc.v.Load().(*AuthStyleCache)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
type authStyleCacheKey struct {
|
||||
url string
|
||||
clientID string
|
||||
}
|
||||
|
||||
// AuthStyleCache is the set of tokenURLs we've successfully used via
|
||||
// RetrieveToken and which style auth we ended up using.
|
||||
// It's called a cache, but it doesn't (yet?) shrink. It's expected that
|
||||
// the set of OAuth2 servers a program contacts over time is fixed and
|
||||
// small.
|
||||
var authStyleCache struct {
|
||||
sync.Mutex
|
||||
m map[string]AuthStyle // keyed by tokenURL
|
||||
}
|
||||
|
||||
// ResetAuthCache resets the global authentication style cache used
|
||||
// for AuthStyleUnknown token requests.
|
||||
func ResetAuthCache() {
|
||||
authStyleCache.Lock()
|
||||
defer authStyleCache.Unlock()
|
||||
authStyleCache.m = nil
|
||||
type AuthStyleCache struct {
|
||||
mu sync.Mutex
|
||||
m map[authStyleCacheKey]AuthStyle
|
||||
}
|
||||
|
||||
// lookupAuthStyle reports which auth style we last used with tokenURL
|
||||
// when calling RetrieveToken and whether we have ever done so.
|
||||
func lookupAuthStyle(tokenURL string) (style AuthStyle, ok bool) {
|
||||
authStyleCache.Lock()
|
||||
defer authStyleCache.Unlock()
|
||||
style, ok = authStyleCache.m[tokenURL]
|
||||
func (c *AuthStyleCache) lookupAuthStyle(tokenURL, clientID string) (style AuthStyle, ok bool) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
style, ok = c.m[authStyleCacheKey{tokenURL, clientID}]
|
||||
return
|
||||
}
|
||||
|
||||
// setAuthStyle adds an entry to authStyleCache, documented above.
|
||||
func setAuthStyle(tokenURL string, v AuthStyle) {
|
||||
authStyleCache.Lock()
|
||||
defer authStyleCache.Unlock()
|
||||
if authStyleCache.m == nil {
|
||||
authStyleCache.m = make(map[string]AuthStyle)
|
||||
func (c *AuthStyleCache) setAuthStyle(tokenURL, clientID string, v AuthStyle) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.m == nil {
|
||||
c.m = make(map[authStyleCacheKey]AuthStyle)
|
||||
}
|
||||
authStyleCache.m[tokenURL] = v
|
||||
c.m[authStyleCacheKey{tokenURL, clientID}] = v
|
||||
}
|
||||
|
||||
// newTokenRequest returns a new *http.Request to retrieve a new token
|
||||
@@ -189,10 +212,10 @@ func cloneURLValues(v url.Values) url.Values {
|
||||
return v2
|
||||
}
|
||||
|
||||
func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle) (*Token, error) {
|
||||
needsAuthStyleProbe := authStyle == 0
|
||||
func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle, styleCache *AuthStyleCache) (*Token, error) {
|
||||
needsAuthStyleProbe := authStyle == AuthStyleUnknown
|
||||
if needsAuthStyleProbe {
|
||||
if style, ok := lookupAuthStyle(tokenURL); ok {
|
||||
if style, ok := styleCache.lookupAuthStyle(tokenURL, clientID); ok {
|
||||
authStyle = style
|
||||
needsAuthStyleProbe = false
|
||||
} else {
|
||||
@@ -222,7 +245,7 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string,
|
||||
token, err = doTokenRoundTrip(ctx, req)
|
||||
}
|
||||
if needsAuthStyleProbe && err == nil {
|
||||
setAuthStyle(tokenURL, authStyle)
|
||||
styleCache.setAuthStyle(tokenURL, clientID, authStyle)
|
||||
}
|
||||
// Don't overwrite `RefreshToken` with an empty value
|
||||
// if this was a token refreshing request.
|
||||
@@ -237,7 +260,7 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20))
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20))
|
||||
r.Body.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
|
||||
@@ -292,7 +315,8 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
|
||||
TokenType: tj.TokenType,
|
||||
RefreshToken: tj.RefreshToken,
|
||||
Expiry: tj.expiry(),
|
||||
Raw: make(map[string]interface{}),
|
||||
ExpiresIn: int64(tj.ExpiresIn),
|
||||
Raw: make(map[string]any),
|
||||
}
|
||||
json.Unmarshal(body, &token.Raw) // no error checks for optional fields
|
||||
}
|
||||
|
||||
+2
-7
@@ -9,8 +9,8 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// HTTPClient is the context key to use with golang.org/x/net/context's
|
||||
// WithValue function to associate an *http.Client value with a context.
|
||||
// HTTPClient is the context key to use with [context.WithValue]
|
||||
// to associate an [*http.Client] value with a context.
|
||||
var HTTPClient ContextKey
|
||||
|
||||
// ContextKey is just an empty struct. It exists so HTTPClient can be
|
||||
@@ -18,16 +18,11 @@ var HTTPClient ContextKey
|
||||
// because nobody else can create a ContextKey, being unexported.
|
||||
type ContextKey struct{}
|
||||
|
||||
var appengineClientHook func(context.Context) *http.Client
|
||||
|
||||
func ContextClient(ctx context.Context) *http.Client {
|
||||
if ctx != nil {
|
||||
if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok {
|
||||
return hc
|
||||
}
|
||||
}
|
||||
if appengineClientHook != nil {
|
||||
return appengineClientHook(ctx)
|
||||
}
|
||||
return http.DefaultClient
|
||||
}
|
||||
+54
-42
@@ -22,9 +22,9 @@ import (
|
||||
)
|
||||
|
||||
// NoContext is the default context you should supply if not using
|
||||
// your own context.Context (see https://golang.org/x/net/context).
|
||||
// your own [context.Context].
|
||||
//
|
||||
// Deprecated: Use context.Background() or context.TODO() instead.
|
||||
// Deprecated: Use [context.Background] or [context.TODO] instead.
|
||||
var NoContext = context.TODO()
|
||||
|
||||
// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op.
|
||||
@@ -37,8 +37,8 @@ func RegisterBrokenAuthHeaderProvider(tokenURL string) {}
|
||||
|
||||
// Config describes a typical 3-legged OAuth2 flow, with both the
|
||||
// client application information and the server's endpoint URLs.
|
||||
// For the client credentials 2-legged OAuth2 flow, see the clientcredentials
|
||||
// package (https://golang.org/x/oauth2/clientcredentials).
|
||||
// For the client credentials 2-legged OAuth2 flow, see the
|
||||
// [golang.org/x/oauth2/clientcredentials] package.
|
||||
type Config struct {
|
||||
// ClientID is the application's ID.
|
||||
ClientID string
|
||||
@@ -46,7 +46,7 @@ type Config struct {
|
||||
// ClientSecret is the application's secret.
|
||||
ClientSecret string
|
||||
|
||||
// Endpoint contains the resource server's token endpoint
|
||||
// Endpoint contains the authorization server's token endpoint
|
||||
// URLs. These are constants specific to each server and are
|
||||
// often available via site-specific packages, such as
|
||||
// google.Endpoint or github.Endpoint.
|
||||
@@ -56,8 +56,12 @@ type Config struct {
|
||||
// the OAuth flow, after the resource owner's URLs.
|
||||
RedirectURL string
|
||||
|
||||
// Scope specifies optional requested permissions.
|
||||
// Scopes specifies optional requested permissions.
|
||||
Scopes []string
|
||||
|
||||
// authStyleCache caches which auth style to use when Endpoint.AuthStyle is
|
||||
// the zero value (AuthStyleAutoDetect).
|
||||
authStyleCache internal.LazyAuthStyleCache
|
||||
}
|
||||
|
||||
// A TokenSource is anything that can return a token.
|
||||
@@ -71,8 +75,9 @@ type TokenSource interface {
|
||||
// Endpoint represents an OAuth 2.0 provider's authorization and token
|
||||
// endpoint URLs.
|
||||
type Endpoint struct {
|
||||
AuthURL string
|
||||
TokenURL string
|
||||
AuthURL string
|
||||
DeviceAuthURL string
|
||||
TokenURL string
|
||||
|
||||
// AuthStyle optionally specifies how the endpoint wants the
|
||||
// client ID & client secret sent. The zero value means to
|
||||
@@ -130,7 +135,7 @@ type setParam struct{ k, v string }
|
||||
|
||||
func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) }
|
||||
|
||||
// SetAuthURLParam builds an AuthCodeOption which passes key/value parameters
|
||||
// SetAuthURLParam builds an [AuthCodeOption] which passes key/value parameters
|
||||
// to a provider's authorization endpoint.
|
||||
func SetAuthURLParam(key, value string) AuthCodeOption {
|
||||
return setParam{key, value}
|
||||
@@ -139,15 +144,19 @@ func SetAuthURLParam(key, value string) AuthCodeOption {
|
||||
// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
|
||||
// that asks for permissions for the required scopes explicitly.
|
||||
//
|
||||
// State is a token to protect the user from CSRF attacks. You must
|
||||
// always provide a non-empty string and validate that it matches the
|
||||
// state query parameter on your redirect callback.
|
||||
// See http://tools.ietf.org/html/rfc6749#section-10.12 for more info.
|
||||
// State is an opaque value used by the client to maintain state between the
|
||||
// request and callback. The authorization server includes this value when
|
||||
// redirecting the user agent back to the client.
|
||||
//
|
||||
// Opts may include AccessTypeOnline or AccessTypeOffline, as well
|
||||
// as ApprovalForce.
|
||||
// It can also be used to pass the PKCE challenge.
|
||||
// See https://www.oauth.com/oauth2-servers/pkce/ for more info.
|
||||
// Opts may include [AccessTypeOnline] or [AccessTypeOffline], as well
|
||||
// as [ApprovalForce].
|
||||
//
|
||||
// To protect against CSRF attacks, opts should include a PKCE challenge
|
||||
// (S256ChallengeOption). Not all servers support PKCE. An alternative is to
|
||||
// generate a random state parameter and verify it after exchange.
|
||||
// See https://datatracker.ietf.org/doc/html/rfc6749#section-10.12 (predating
|
||||
// PKCE), https://www.oauth.com/oauth2-servers/pkce/ and
|
||||
// https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-09.html#name-cross-site-request-forgery (describing both approaches)
|
||||
func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(c.Endpoint.AuthURL)
|
||||
@@ -162,7 +171,6 @@ func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string {
|
||||
v.Set("scope", strings.Join(c.Scopes, " "))
|
||||
}
|
||||
if state != "" {
|
||||
// TODO(light): Docs say never to omit state; don't allow empty.
|
||||
v.Set("state", state)
|
||||
}
|
||||
for _, opt := range opts {
|
||||
@@ -186,7 +194,7 @@ func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string {
|
||||
// and when other authorization grant types are not available."
|
||||
// See https://tools.ietf.org/html/rfc6749#section-4.3 for more info.
|
||||
//
|
||||
// The provided context optionally controls which HTTP client is used. See the HTTPClient variable.
|
||||
// The provided context optionally controls which HTTP client is used. See the [HTTPClient] variable.
|
||||
func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) {
|
||||
v := url.Values{
|
||||
"grant_type": {"password"},
|
||||
@@ -204,13 +212,14 @@ func (c *Config) PasswordCredentialsToken(ctx context.Context, username, passwor
|
||||
// It is used after a resource provider redirects the user back
|
||||
// to the Redirect URI (the URL obtained from AuthCodeURL).
|
||||
//
|
||||
// The provided context optionally controls which HTTP client is used. See the HTTPClient variable.
|
||||
// The provided context optionally controls which HTTP client is used. See the [HTTPClient] variable.
|
||||
//
|
||||
// The code will be in the *http.Request.FormValue("code"). Before
|
||||
// calling Exchange, be sure to validate FormValue("state").
|
||||
// The code will be in the [http.Request.FormValue]("code"). Before
|
||||
// calling Exchange, be sure to validate [http.Request.FormValue]("state") if you are
|
||||
// using it to protect against CSRF attacks.
|
||||
//
|
||||
// Opts may include the PKCE verifier code if previously used in AuthCodeURL.
|
||||
// See https://www.oauth.com/oauth2-servers/pkce/ for more info.
|
||||
// If using PKCE to protect against CSRF attacks, opts should include a
|
||||
// VerifierOption.
|
||||
func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) {
|
||||
v := url.Values{
|
||||
"grant_type": {"authorization_code"},
|
||||
@@ -233,10 +242,10 @@ func (c *Config) Client(ctx context.Context, t *Token) *http.Client {
|
||||
return NewClient(ctx, c.TokenSource(ctx, t))
|
||||
}
|
||||
|
||||
// TokenSource returns a TokenSource that returns t until t expires,
|
||||
// TokenSource returns a [TokenSource] that returns t until t expires,
|
||||
// automatically refreshing it as necessary using the provided context.
|
||||
//
|
||||
// Most users will use Config.Client instead.
|
||||
// Most users will use [Config.Client] instead.
|
||||
func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
|
||||
tkr := &tokenRefresher{
|
||||
ctx: ctx,
|
||||
@@ -251,7 +260,7 @@ func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
|
||||
}
|
||||
}
|
||||
|
||||
// tokenRefresher is a TokenSource that makes "grant_type"=="refresh_token"
|
||||
// tokenRefresher is a TokenSource that makes "grant_type=refresh_token"
|
||||
// HTTP requests to renew a token using a RefreshToken.
|
||||
type tokenRefresher struct {
|
||||
ctx context.Context // used to get HTTP requests
|
||||
@@ -279,7 +288,7 @@ func (tf *tokenRefresher) Token() (*Token, error) {
|
||||
if tf.refreshToken != tk.RefreshToken {
|
||||
tf.refreshToken = tk.RefreshToken
|
||||
}
|
||||
return tk, err
|
||||
return tk, nil
|
||||
}
|
||||
|
||||
// reuseTokenSource is a TokenSource that holds a single token in memory
|
||||
@@ -296,8 +305,7 @@ type reuseTokenSource struct {
|
||||
}
|
||||
|
||||
// Token returns the current token if it's still valid, else will
|
||||
// refresh the current token (using r.Context for HTTP client
|
||||
// information) and return the new one.
|
||||
// refresh the current token and return the new one.
|
||||
func (s *reuseTokenSource) Token() (*Token, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
@@ -313,7 +321,7 @@ func (s *reuseTokenSource) Token() (*Token, error) {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// StaticTokenSource returns a TokenSource that always returns the same token.
|
||||
// StaticTokenSource returns a [TokenSource] that always returns the same token.
|
||||
// Because the provided token t is never refreshed, StaticTokenSource is only
|
||||
// useful for tokens that never expire.
|
||||
func StaticTokenSource(t *Token) TokenSource {
|
||||
@@ -329,16 +337,16 @@ func (s staticTokenSource) Token() (*Token, error) {
|
||||
return s.t, nil
|
||||
}
|
||||
|
||||
// HTTPClient is the context key to use with golang.org/x/net/context's
|
||||
// WithValue function to associate an *http.Client value with a context.
|
||||
// HTTPClient is the context key to use with [context.WithValue]
|
||||
// to associate a [*http.Client] value with a context.
|
||||
var HTTPClient internal.ContextKey
|
||||
|
||||
// NewClient creates an *http.Client from a Context and TokenSource.
|
||||
// NewClient creates an [*http.Client] from a [context.Context] and [TokenSource].
|
||||
// The returned client is not valid beyond the lifetime of the context.
|
||||
//
|
||||
// Note that if a custom *http.Client is provided via the Context it
|
||||
// Note that if a custom [*http.Client] is provided via the [context.Context] it
|
||||
// is used only for token acquisition and is not used to configure the
|
||||
// *http.Client returned from NewClient.
|
||||
// [*http.Client] returned from NewClient.
|
||||
//
|
||||
// As a special case, if src is nil, a non-OAuth2 client is returned
|
||||
// using the provided context. This exists to support related OAuth2
|
||||
@@ -347,15 +355,19 @@ func NewClient(ctx context.Context, src TokenSource) *http.Client {
|
||||
if src == nil {
|
||||
return internal.ContextClient(ctx)
|
||||
}
|
||||
cc := internal.ContextClient(ctx)
|
||||
return &http.Client{
|
||||
Transport: &Transport{
|
||||
Base: internal.ContextClient(ctx).Transport,
|
||||
Base: cc.Transport,
|
||||
Source: ReuseTokenSource(nil, src),
|
||||
},
|
||||
CheckRedirect: cc.CheckRedirect,
|
||||
Jar: cc.Jar,
|
||||
Timeout: cc.Timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// ReuseTokenSource returns a TokenSource which repeatedly returns the
|
||||
// ReuseTokenSource returns a [TokenSource] which repeatedly returns the
|
||||
// same token as long as it's valid, starting with t.
|
||||
// When its cached token is invalid, a new token is obtained from src.
|
||||
//
|
||||
@@ -363,10 +375,10 @@ func NewClient(ctx context.Context, src TokenSource) *http.Client {
|
||||
// (such as a file on disk) between runs of a program, rather than
|
||||
// obtaining new tokens unnecessarily.
|
||||
//
|
||||
// The initial token t may be nil, in which case the TokenSource is
|
||||
// The initial token t may be nil, in which case the [TokenSource] is
|
||||
// wrapped in a caching version if it isn't one already. This also
|
||||
// means it's always safe to wrap ReuseTokenSource around any other
|
||||
// TokenSource without adverse effects.
|
||||
// [TokenSource] without adverse effects.
|
||||
func ReuseTokenSource(t *Token, src TokenSource) TokenSource {
|
||||
// Don't wrap a reuseTokenSource in itself. That would work,
|
||||
// but cause an unnecessary number of mutex operations.
|
||||
@@ -384,8 +396,8 @@ func ReuseTokenSource(t *Token, src TokenSource) TokenSource {
|
||||
}
|
||||
}
|
||||
|
||||
// ReuseTokenSource returns a TokenSource that acts in the same manner as the
|
||||
// TokenSource returned by ReuseTokenSource, except the expiry buffer is
|
||||
// ReuseTokenSourceWithExpiry returns a [TokenSource] that acts in the same manner as the
|
||||
// [TokenSource] returned by [ReuseTokenSource], except the expiry buffer is
|
||||
// configurable. The expiration time of a token is calculated as
|
||||
// t.Expiry.Add(-earlyExpiry).
|
||||
func ReuseTokenSourceWithExpiry(t *Token, src TokenSource, earlyExpiry time.Duration) TokenSource {
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// Copyright 2023 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 oauth2
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
const (
|
||||
codeChallengeKey = "code_challenge"
|
||||
codeChallengeMethodKey = "code_challenge_method"
|
||||
codeVerifierKey = "code_verifier"
|
||||
)
|
||||
|
||||
// GenerateVerifier generates a PKCE code verifier with 32 octets of randomness.
|
||||
// This follows recommendations in RFC 7636.
|
||||
//
|
||||
// A fresh verifier should be generated for each authorization.
|
||||
// The resulting verifier should be passed to [Config.AuthCodeURL] or [Config.DeviceAuth]
|
||||
// with [S256ChallengeOption], and to [Config.Exchange] or [Config.DeviceAccessToken]
|
||||
// with [VerifierOption].
|
||||
func GenerateVerifier() string {
|
||||
// "RECOMMENDED that the output of a suitable random number generator be
|
||||
// used to create a 32-octet sequence. The octet sequence is then
|
||||
// base64url-encoded to produce a 43-octet URL-safe string to use as the
|
||||
// code verifier."
|
||||
// https://datatracker.ietf.org/doc/html/rfc7636#section-4.1
|
||||
data := make([]byte, 32)
|
||||
if _, err := rand.Read(data); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return base64.RawURLEncoding.EncodeToString(data)
|
||||
}
|
||||
|
||||
// VerifierOption returns a PKCE code verifier [AuthCodeOption]. It should only be
|
||||
// passed to [Config.Exchange] or [Config.DeviceAccessToken].
|
||||
func VerifierOption(verifier string) AuthCodeOption {
|
||||
return setParam{k: codeVerifierKey, v: verifier}
|
||||
}
|
||||
|
||||
// S256ChallengeFromVerifier returns a PKCE code challenge derived from verifier with method S256.
|
||||
//
|
||||
// Prefer to use [S256ChallengeOption] where possible.
|
||||
func S256ChallengeFromVerifier(verifier string) string {
|
||||
sha := sha256.Sum256([]byte(verifier))
|
||||
return base64.RawURLEncoding.EncodeToString(sha[:])
|
||||
}
|
||||
|
||||
// S256ChallengeOption derives a PKCE code challenge derived from verifier with
|
||||
// method S256. It should be passed to [Config.AuthCodeURL] or [Config.DeviceAuth]
|
||||
// only.
|
||||
func S256ChallengeOption(verifier string) AuthCodeOption {
|
||||
return challengeOption{
|
||||
challenge_method: "S256",
|
||||
challenge: S256ChallengeFromVerifier(verifier),
|
||||
}
|
||||
}
|
||||
|
||||
type challengeOption struct{ challenge_method, challenge string }
|
||||
|
||||
func (p challengeOption) setValue(m url.Values) {
|
||||
m.Set(codeChallengeMethodKey, p.challenge_method)
|
||||
m.Set(codeChallengeKey, p.challenge)
|
||||
}
|
||||
+17
-9
@@ -44,14 +44,21 @@ type Token struct {
|
||||
|
||||
// Expiry is the optional expiration time of the access token.
|
||||
//
|
||||
// If zero, TokenSource implementations will reuse the same
|
||||
// If zero, [TokenSource] implementations will reuse the same
|
||||
// token forever and RefreshToken or equivalent
|
||||
// mechanisms for that TokenSource will not be used.
|
||||
Expiry time.Time `json:"expiry,omitempty"`
|
||||
|
||||
// ExpiresIn is the OAuth2 wire format "expires_in" field,
|
||||
// which specifies how many seconds later the token expires,
|
||||
// relative to an unknown time base approximately around "now".
|
||||
// It is the application's responsibility to populate
|
||||
// `Expiry` from `ExpiresIn` when required.
|
||||
ExpiresIn int64 `json:"expires_in,omitempty"`
|
||||
|
||||
// raw optionally contains extra metadata from the server
|
||||
// when updating a token.
|
||||
raw interface{}
|
||||
raw any
|
||||
|
||||
// expiryDelta is used to calculate when a token is considered
|
||||
// expired, by subtracting from Expiry. If zero, defaultExpiryDelta
|
||||
@@ -79,16 +86,16 @@ func (t *Token) Type() string {
|
||||
// SetAuthHeader sets the Authorization header to r using the access
|
||||
// token in t.
|
||||
//
|
||||
// This method is unnecessary when using Transport or an HTTP Client
|
||||
// This method is unnecessary when using [Transport] or an HTTP Client
|
||||
// returned by this package.
|
||||
func (t *Token) SetAuthHeader(r *http.Request) {
|
||||
r.Header.Set("Authorization", t.Type()+" "+t.AccessToken)
|
||||
}
|
||||
|
||||
// WithExtra returns a new Token that's a clone of t, but using the
|
||||
// WithExtra returns a new [Token] that's a clone of t, but using the
|
||||
// provided raw extra map. This is only intended for use by packages
|
||||
// implementing derivative OAuth2 flows.
|
||||
func (t *Token) WithExtra(extra interface{}) *Token {
|
||||
func (t *Token) WithExtra(extra any) *Token {
|
||||
t2 := new(Token)
|
||||
*t2 = *t
|
||||
t2.raw = extra
|
||||
@@ -98,8 +105,8 @@ func (t *Token) WithExtra(extra interface{}) *Token {
|
||||
// Extra returns an extra field.
|
||||
// Extra fields are key-value pairs returned by the server as a
|
||||
// part of the token retrieval response.
|
||||
func (t *Token) Extra(key string) interface{} {
|
||||
if raw, ok := t.raw.(map[string]interface{}); ok {
|
||||
func (t *Token) Extra(key string) any {
|
||||
if raw, ok := t.raw.(map[string]any); ok {
|
||||
return raw[key]
|
||||
}
|
||||
|
||||
@@ -156,15 +163,16 @@ func tokenFromInternal(t *internal.Token) *Token {
|
||||
TokenType: t.TokenType,
|
||||
RefreshToken: t.RefreshToken,
|
||||
Expiry: t.Expiry,
|
||||
ExpiresIn: t.ExpiresIn,
|
||||
raw: t.Raw,
|
||||
}
|
||||
}
|
||||
|
||||
// retrieveToken takes a *Config and uses that to retrieve an *internal.Token.
|
||||
// This token is then mapped from *internal.Token into an *oauth2.Token which is returned along
|
||||
// with an error..
|
||||
// with an error.
|
||||
func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) {
|
||||
tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle))
|
||||
tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle), c.authStyleCache.Get())
|
||||
if err != nil {
|
||||
if rErr, ok := err.(*internal.RetrieveError); ok {
|
||||
return nil, (*RetrieveError)(rErr)
|
||||
|
||||
+5
-19
@@ -11,12 +11,12 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests,
|
||||
// wrapping a base RoundTripper and adding an Authorization header
|
||||
// with a token from the supplied Sources.
|
||||
// Transport is an [http.RoundTripper] that makes OAuth 2.0 HTTP requests,
|
||||
// wrapping a base [http.RoundTripper] and adding an Authorization header
|
||||
// with a token from the supplied [TokenSource].
|
||||
//
|
||||
// Transport is a low-level mechanism. Most code will use the
|
||||
// higher-level Config.Client method instead.
|
||||
// higher-level [Config.Client] method instead.
|
||||
type Transport struct {
|
||||
// Source supplies the token to add to outgoing requests'
|
||||
// Authorization headers.
|
||||
@@ -47,7 +47,7 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req2 := cloneRequest(req) // per RoundTripper contract
|
||||
req2 := req.Clone(req.Context())
|
||||
token.SetAuthHeader(req2)
|
||||
|
||||
// req.Body is assumed to be closed by the base RoundTripper.
|
||||
@@ -73,17 +73,3 @@ func (t *Transport) base() http.RoundTripper {
|
||||
}
|
||||
return http.DefaultTransport
|
||||
}
|
||||
|
||||
// cloneRequest returns a clone of the provided *http.Request.
|
||||
// The clone is a shallow copy of the struct and its Header map.
|
||||
func cloneRequest(r *http.Request) *http.Request {
|
||||
// shallow copy of the struct
|
||||
r2 := new(http.Request)
|
||||
*r2 = *r
|
||||
// deep copy of the Header
|
||||
r2.Header = make(http.Header, len(r.Header))
|
||||
for k, s := range r.Header {
|
||||
r2.Header[k] = append([]string(nil), s...)
|
||||
}
|
||||
return r2
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
Copyright 2009 The Go Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
|
||||
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
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
|
||||
+25
-6
@@ -4,6 +4,9 @@
|
||||
|
||||
// Package errgroup provides synchronization, error propagation, and Context
|
||||
// cancelation for groups of goroutines working on subtasks of a common task.
|
||||
//
|
||||
// [errgroup.Group] is related to [sync.WaitGroup] but adds handling of tasks
|
||||
// returning errors.
|
||||
package errgroup
|
||||
|
||||
import (
|
||||
@@ -15,7 +18,7 @@ import (
|
||||
type token struct{}
|
||||
|
||||
// A Group is a collection of goroutines working on subtasks that are part of
|
||||
// the same overall task.
|
||||
// the same overall task. A Group should not be reused for different tasks.
|
||||
//
|
||||
// A zero Group is valid, has no limit on the number of active goroutines,
|
||||
// and does not cancel on error.
|
||||
@@ -43,7 +46,7 @@ func (g *Group) done() {
|
||||
// returns a non-nil error or the first time Wait returns, whichever occurs
|
||||
// first.
|
||||
func WithContext(ctx context.Context) (*Group, context.Context) {
|
||||
ctx, cancel := withCancelCause(ctx)
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
return &Group{cancel: cancel}, ctx
|
||||
}
|
||||
|
||||
@@ -58,11 +61,14 @@ func (g *Group) Wait() error {
|
||||
}
|
||||
|
||||
// Go calls the given function in a new goroutine.
|
||||
// It blocks until the new goroutine can be added without the number of
|
||||
// active goroutines in the group exceeding the configured limit.
|
||||
//
|
||||
// The first call to return a non-nil error cancels the group's context, if the
|
||||
// group was created by calling WithContext. The error will be returned by Wait.
|
||||
// The first call to Go must happen before a Wait.
|
||||
// It blocks until the new goroutine can be added without the number of
|
||||
// goroutines in the group exceeding the configured limit.
|
||||
//
|
||||
// The first goroutine in the group that returns a non-nil error will
|
||||
// cancel the associated Context, if any. The error will be returned
|
||||
// by Wait.
|
||||
func (g *Group) Go(f func() error) {
|
||||
if g.sem != nil {
|
||||
g.sem <- token{}
|
||||
@@ -72,6 +78,18 @@ func (g *Group) Go(f func() error) {
|
||||
go func() {
|
||||
defer g.done()
|
||||
|
||||
// It is tempting to propagate panics from f()
|
||||
// up to the goroutine that calls Wait, but
|
||||
// it creates more problems than it solves:
|
||||
// - it delays panics arbitrarily,
|
||||
// making bugs harder to detect;
|
||||
// - it turns f's panic stack into a mere value,
|
||||
// hiding it from crash-monitoring tools;
|
||||
// - it risks deadlocks that hide the panic entirely,
|
||||
// if f's panic leaves the program in a state
|
||||
// that prevents the Wait call from being reached.
|
||||
// See #53757, #74275, #74304, #74306.
|
||||
|
||||
if err := f(); err != nil {
|
||||
g.errOnce.Do(func() {
|
||||
g.err = err
|
||||
@@ -115,6 +133,7 @@ func (g *Group) TryGo(f func() error) bool {
|
||||
|
||||
// SetLimit limits the number of active goroutines in this group to at most n.
|
||||
// A negative value indicates no limit.
|
||||
// A limit of zero will prevent any new goroutines from being added.
|
||||
//
|
||||
// Any subsequent call to the Go method will block until it can add an active
|
||||
// goroutine without exceeding the configured limit.
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
// Copyright 2023 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.20
|
||||
// +build go1.20
|
||||
|
||||
package errgroup
|
||||
|
||||
import "context"
|
||||
|
||||
func withCancelCause(parent context.Context) (context.Context, func(error)) {
|
||||
return context.WithCancelCause(parent)
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
// Copyright 2023 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.20
|
||||
// +build !go1.20
|
||||
|
||||
package errgroup
|
||||
|
||||
import "context"
|
||||
|
||||
func withCancelCause(parent context.Context) (context.Context, func(error)) {
|
||||
ctx, cancel := context.WithCancel(parent)
|
||||
return ctx, func(error) { cancel() }
|
||||
}
|
||||
+33
-9
@@ -35,11 +35,25 @@ type Weighted struct {
|
||||
// Acquire acquires the semaphore with a weight of n, blocking until resources
|
||||
// are available or ctx is done. On success, returns nil. On failure, returns
|
||||
// ctx.Err() and leaves the semaphore unchanged.
|
||||
//
|
||||
// If ctx is already done, Acquire may still succeed without blocking.
|
||||
func (s *Weighted) Acquire(ctx context.Context, n int64) error {
|
||||
done := ctx.Done()
|
||||
|
||||
s.mu.Lock()
|
||||
select {
|
||||
case <-done:
|
||||
// ctx becoming done has "happened before" acquiring the semaphore,
|
||||
// whether it became done before the call began or while we were
|
||||
// waiting for the mutex. We prefer to fail even if we could acquire
|
||||
// the mutex without blocking.
|
||||
s.mu.Unlock()
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
if s.size-s.cur >= n && s.waiters.Len() == 0 {
|
||||
// Since we hold s.mu and haven't synchronized since checking done, if
|
||||
// ctx becomes done before we return here, it becoming done must have
|
||||
// "happened concurrently" with this call - it cannot "happen before"
|
||||
// we return in this branch. So, we're ok to always acquire here.
|
||||
s.cur += n
|
||||
s.mu.Unlock()
|
||||
return nil
|
||||
@@ -48,7 +62,7 @@ func (s *Weighted) Acquire(ctx context.Context, n int64) error {
|
||||
if n > s.size {
|
||||
// Don't make other Acquire calls block on one that's doomed to fail.
|
||||
s.mu.Unlock()
|
||||
<-ctx.Done()
|
||||
<-done
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
@@ -58,14 +72,14 @@ func (s *Weighted) Acquire(ctx context.Context, n int64) error {
|
||||
s.mu.Unlock()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
err := ctx.Err()
|
||||
case <-done:
|
||||
s.mu.Lock()
|
||||
select {
|
||||
case <-ready:
|
||||
// Acquired the semaphore after we were canceled. Rather than trying to
|
||||
// fix up the queue, just pretend we didn't notice the cancelation.
|
||||
err = nil
|
||||
// Acquired the semaphore after we were canceled.
|
||||
// Pretend we didn't and put the tokens back.
|
||||
s.cur -= n
|
||||
s.notifyWaiters()
|
||||
default:
|
||||
isFront := s.waiters.Front() == elem
|
||||
s.waiters.Remove(elem)
|
||||
@@ -75,9 +89,19 @@ func (s *Weighted) Acquire(ctx context.Context, n int64) error {
|
||||
}
|
||||
}
|
||||
s.mu.Unlock()
|
||||
return err
|
||||
return ctx.Err()
|
||||
|
||||
case <-ready:
|
||||
// Acquired the semaphore. Check that ctx isn't already done.
|
||||
// We check the done channel instead of calling ctx.Err because we
|
||||
// already have the channel, and ctx.Err is O(n) with the nesting
|
||||
// depth of ctx.
|
||||
select {
|
||||
case <-done:
|
||||
s.Release(n)
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
Copyright 2009 The Go Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
|
||||
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
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ from the generated architecture-specific files listed below, and merge these
|
||||
into a common file for each OS.
|
||||
|
||||
The merge is performed in the following steps:
|
||||
1. Construct the set of common code that is idential in all architecture-specific files.
|
||||
1. Construct the set of common code that is identical in all architecture-specific files.
|
||||
2. Write this common code to the merged file.
|
||||
3. Remove the common code from all architecture-specific files.
|
||||
|
||||
|
||||
+317
-358
@@ -9,9 +9,11 @@
|
||||
#define PSALAA 1208(R0)
|
||||
#define GTAB64(x) 80(x)
|
||||
#define LCA64(x) 88(x)
|
||||
#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
|
||||
#define CAA(x) 8(x)
|
||||
#define EDCHPXV(x) 1016(x) // in the CAA
|
||||
#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
|
||||
#define CEECAATHDID(x) 976(x) // in the CAA
|
||||
#define EDCHPXV(x) 1016(x) // in the CAA
|
||||
#define GOCB(x) 1104(x) // in the CAA
|
||||
|
||||
// SS_*, where x=SAVSTACK_ASYNC
|
||||
#define SS_LE(x) 0(x)
|
||||
@@ -19,394 +21,125 @@
|
||||
#define SS_ERRNO(x) 16(x)
|
||||
#define SS_ERRNOJR(x) 20(x)
|
||||
|
||||
#define LE_CALL BYTE $0x0D; BYTE $0x76; // BL R7, R6
|
||||
// Function Descriptor Offsets
|
||||
#define __errno 0x156*16
|
||||
#define __err2ad 0x16C*16
|
||||
|
||||
TEXT ·clearErrno(SB),NOSPLIT,$0-0
|
||||
BL addrerrno<>(SB)
|
||||
MOVD $0, 0(R3)
|
||||
// Call Instructions
|
||||
#define LE_CALL BYTE $0x0D; BYTE $0x76 // BL R7, R6
|
||||
#define SVC_LOAD BYTE $0x0A; BYTE $0x08 // SVC 08 LOAD
|
||||
#define SVC_DELETE BYTE $0x0A; BYTE $0x09 // SVC 09 DELETE
|
||||
|
||||
DATA zosLibVec<>(SB)/8, $0
|
||||
GLOBL zosLibVec<>(SB), NOPTR, $8
|
||||
|
||||
TEXT ·initZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
MOVD CAA(R8), R8
|
||||
MOVD EDCHPXV(R8), R8
|
||||
MOVD R8, zosLibVec<>(SB)
|
||||
RET
|
||||
|
||||
TEXT ·GetZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
|
||||
MOVD zosLibVec<>(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·clearErrno(SB), NOSPLIT, $0-0
|
||||
BL addrerrno<>(SB)
|
||||
MOVD $0, 0(R3)
|
||||
RET
|
||||
|
||||
// Returns the address of errno in R3.
|
||||
TEXT addrerrno<>(SB),NOSPLIT|NOFRAME,$0-0
|
||||
TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get __errno FuncDesc.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
ADD $(0x156*16), R9
|
||||
LMG 0(R9), R5, R6
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
ADD $(__errno), R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Switch to saved LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Call __errno function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
|
||||
// Switch back to Go stack.
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
RET
|
||||
|
||||
TEXT ·syscall_syscall(SB),NOSPLIT,$0-56
|
||||
BL runtime·entersyscall(SB)
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+32(FP)
|
||||
MOVD R0, r2+40(FP)
|
||||
MOVD R0, err+48(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL addrerrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+48(FP)
|
||||
done:
|
||||
BL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·syscall_rawsyscall(SB),NOSPLIT,$0-56
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+32(FP)
|
||||
MOVD R0, r2+40(FP)
|
||||
MOVD R0, err+48(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL addrerrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+48(FP)
|
||||
done:
|
||||
RET
|
||||
|
||||
TEXT ·syscall_syscall6(SB),NOSPLIT,$0-80
|
||||
BL runtime·entersyscall(SB)
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Fill in parameter list.
|
||||
MOVD a4+32(FP), R12
|
||||
MOVD R12, (2176+24)(R4)
|
||||
MOVD a5+40(FP), R12
|
||||
MOVD R12, (2176+32)(R4)
|
||||
MOVD a6+48(FP), R12
|
||||
MOVD R12, (2176+40)(R4)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+56(FP)
|
||||
MOVD R0, r2+64(FP)
|
||||
MOVD R0, err+72(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL addrerrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+72(FP)
|
||||
done:
|
||||
BL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·syscall_rawsyscall6(SB),NOSPLIT,$0-80
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Fill in parameter list.
|
||||
MOVD a4+32(FP), R12
|
||||
MOVD R12, (2176+24)(R4)
|
||||
MOVD a5+40(FP), R12
|
||||
MOVD R12, (2176+32)(R4)
|
||||
MOVD a6+48(FP), R12
|
||||
MOVD R12, (2176+40)(R4)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+56(FP)
|
||||
MOVD R0, r2+64(FP)
|
||||
MOVD R0, err+72(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL ·rrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+72(FP)
|
||||
done:
|
||||
RET
|
||||
|
||||
TEXT ·syscall_syscall9(SB),NOSPLIT,$0
|
||||
BL runtime·entersyscall(SB)
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Fill in parameter list.
|
||||
MOVD a4+32(FP), R12
|
||||
MOVD R12, (2176+24)(R4)
|
||||
MOVD a5+40(FP), R12
|
||||
MOVD R12, (2176+32)(R4)
|
||||
MOVD a6+48(FP), R12
|
||||
MOVD R12, (2176+40)(R4)
|
||||
MOVD a7+56(FP), R12
|
||||
MOVD R12, (2176+48)(R4)
|
||||
MOVD a8+64(FP), R12
|
||||
MOVD R12, (2176+56)(R4)
|
||||
MOVD a9+72(FP), R12
|
||||
MOVD R12, (2176+64)(R4)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+80(FP)
|
||||
MOVD R0, r2+88(FP)
|
||||
MOVD R0, err+96(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL addrerrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+96(FP)
|
||||
done:
|
||||
BL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·syscall_rawsyscall9(SB),NOSPLIT,$0
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Fill in parameter list.
|
||||
MOVD a4+32(FP), R12
|
||||
MOVD R12, (2176+24)(R4)
|
||||
MOVD a5+40(FP), R12
|
||||
MOVD R12, (2176+32)(R4)
|
||||
MOVD a6+48(FP), R12
|
||||
MOVD R12, (2176+40)(R4)
|
||||
MOVD a7+56(FP), R12
|
||||
MOVD R12, (2176+48)(R4)
|
||||
MOVD a8+64(FP), R12
|
||||
MOVD R12, (2176+56)(R4)
|
||||
MOVD a9+72(FP), R12
|
||||
MOVD R12, (2176+64)(R4)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+80(FP)
|
||||
MOVD R0, r2+88(FP)
|
||||
MOVD R0, err+96(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL addrerrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+96(FP)
|
||||
done:
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
RET
|
||||
|
||||
// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
|
||||
TEXT ·svcCall(SB),NOSPLIT,$0
|
||||
BL runtime·save_g(SB) // Save g and stack pointer
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD R15, 0(R9)
|
||||
TEXT ·svcCall(SB), NOSPLIT, $0
|
||||
BL runtime·save_g(SB) // Save g and stack pointer
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD R15, 0(R9)
|
||||
|
||||
MOVD argv+8(FP), R1 // Move function arguments into registers
|
||||
MOVD dsa+16(FP), g
|
||||
MOVD fnptr+0(FP), R15
|
||||
MOVD argv+8(FP), R1 // Move function arguments into registers
|
||||
MOVD dsa+16(FP), g
|
||||
MOVD fnptr+0(FP), R15
|
||||
|
||||
BYTE $0x0D // Branch to function
|
||||
BYTE $0xEF
|
||||
BYTE $0x0D // Branch to function
|
||||
BYTE $0xEF
|
||||
|
||||
BL runtime·load_g(SB) // Restore g and stack pointer
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R15
|
||||
BL runtime·load_g(SB) // Restore g and stack pointer
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R15
|
||||
|
||||
RET
|
||||
|
||||
// func svcLoad(name *byte) unsafe.Pointer
|
||||
TEXT ·svcLoad(SB),NOSPLIT,$0
|
||||
MOVD R15, R2 // Save go stack pointer
|
||||
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||
MOVD $0x80000000, R1
|
||||
MOVD $0, R15
|
||||
BYTE $0x0A // SVC 08 LOAD
|
||||
BYTE $0x08
|
||||
MOVW R15, R3 // Save return code from SVC
|
||||
MOVD R2, R15 // Restore go stack pointer
|
||||
CMP R3, $0 // Check SVC return code
|
||||
BNE error
|
||||
TEXT ·svcLoad(SB), NOSPLIT, $0
|
||||
MOVD R15, R2 // Save go stack pointer
|
||||
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||
MOVD $0x80000000, R1
|
||||
MOVD $0, R15
|
||||
SVC_LOAD
|
||||
MOVW R15, R3 // Save return code from SVC
|
||||
MOVD R2, R15 // Restore go stack pointer
|
||||
CMP R3, $0 // Check SVC return code
|
||||
BNE error
|
||||
|
||||
MOVD $-2, R3 // Reset last bit of entry point to zero
|
||||
AND R0, R3
|
||||
MOVD R3, addr+8(FP) // Return entry point returned by SVC
|
||||
CMP R0, R3 // Check if last bit of entry point was set
|
||||
BNE done
|
||||
MOVD $-2, R3 // Reset last bit of entry point to zero
|
||||
AND R0, R3
|
||||
MOVD R3, ret+8(FP) // Return entry point returned by SVC
|
||||
CMP R0, R3 // Check if last bit of entry point was set
|
||||
BNE done
|
||||
|
||||
MOVD R15, R2 // Save go stack pointer
|
||||
MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
|
||||
BYTE $0x0A // SVC 09 DELETE
|
||||
BYTE $0x09
|
||||
MOVD R2, R15 // Restore go stack pointer
|
||||
MOVD R15, R2 // Save go stack pointer
|
||||
MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
|
||||
SVC_DELETE
|
||||
MOVD R2, R15 // Restore go stack pointer
|
||||
|
||||
error:
|
||||
MOVD $0, addr+8(FP) // Return 0 on failure
|
||||
MOVD $0, ret+8(FP) // Return 0 on failure
|
||||
|
||||
done:
|
||||
XOR R0, R0 // Reset r0 to 0
|
||||
XOR R0, R0 // Reset r0 to 0
|
||||
RET
|
||||
|
||||
// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
|
||||
TEXT ·svcUnload(SB),NOSPLIT,$0
|
||||
MOVD R15, R2 // Save go stack pointer
|
||||
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||
MOVD addr+8(FP), R15
|
||||
BYTE $0x0A // SVC 09
|
||||
BYTE $0x09
|
||||
XOR R0, R0 // Reset r0 to 0
|
||||
MOVD R15, R1 // Save SVC return code
|
||||
MOVD R2, R15 // Restore go stack pointer
|
||||
MOVD R1, rc+0(FP) // Return SVC return code
|
||||
TEXT ·svcUnload(SB), NOSPLIT, $0
|
||||
MOVD R15, R2 // Save go stack pointer
|
||||
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||
MOVD fnptr+8(FP), R15
|
||||
SVC_DELETE
|
||||
XOR R0, R0 // Reset r0 to 0
|
||||
MOVD R15, R1 // Save SVC return code
|
||||
MOVD R2, R15 // Restore go stack pointer
|
||||
MOVD R1, ret+16(FP) // Return SVC return code
|
||||
RET
|
||||
|
||||
// func gettid() uint64
|
||||
@@ -417,7 +150,233 @@ TEXT ·gettid(SB), NOSPLIT, $0
|
||||
|
||||
// Get CEECAATHDID
|
||||
MOVD CAA(R8), R9
|
||||
MOVD 0x3D0(R9), R9
|
||||
MOVD CEECAATHDID(R9), R9
|
||||
MOVD R9, ret+0(FP)
|
||||
|
||||
RET
|
||||
|
||||
//
|
||||
// Call LE function, if the return is -1
|
||||
// errno and errno2 is retrieved
|
||||
//
|
||||
TEXT ·CallLeFuncWithErr(SB), NOSPLIT, $0
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
MOVD CAA(R8), R9
|
||||
MOVD g, GOCB(R9)
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
|
||||
MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
|
||||
|
||||
MOVD parms_base+8(FP), R7 // R7 -> argument array
|
||||
MOVD parms_len+16(FP), R8 // R8 number of arguments
|
||||
|
||||
// arg 1 ---> R1
|
||||
CMP R8, $0
|
||||
BEQ docall
|
||||
SUB $1, R8
|
||||
MOVD 0(R7), R1
|
||||
|
||||
// arg 2 ---> R2
|
||||
CMP R8, $0
|
||||
BEQ docall
|
||||
SUB $1, R8
|
||||
ADD $8, R7
|
||||
MOVD 0(R7), R2
|
||||
|
||||
// arg 3 --> R3
|
||||
CMP R8, $0
|
||||
BEQ docall
|
||||
SUB $1, R8
|
||||
ADD $8, R7
|
||||
MOVD 0(R7), R3
|
||||
|
||||
CMP R8, $0
|
||||
BEQ docall
|
||||
MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
|
||||
|
||||
repeat:
|
||||
ADD $8, R7
|
||||
MOVD 0(R7), R0 // advance arg pointer by 8 byte
|
||||
ADD $8, R6 // advance LE argument address by 8 byte
|
||||
MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
|
||||
SUB $1, R8
|
||||
CMP R8, $0
|
||||
BNE repeat
|
||||
|
||||
docall:
|
||||
MOVD funcdesc+0(FP), R8 // R8-> function descriptor
|
||||
LMG 0(R8), R5, R6
|
||||
MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
|
||||
LE_CALL // balr R7, R6 (return #1)
|
||||
NOPH
|
||||
MOVD R3, ret+32(FP)
|
||||
CMP R3, $-1 // compare result to -1
|
||||
BNE done
|
||||
|
||||
// retrieve errno and errno2
|
||||
MOVD zosLibVec<>(SB), R8
|
||||
ADD $(__errno), R8
|
||||
LMG 0(R8), R5, R6
|
||||
LE_CALL // balr R7, R6 __errno (return #3)
|
||||
NOPH
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+48(FP)
|
||||
MOVD zosLibVec<>(SB), R8
|
||||
ADD $(__err2ad), R8
|
||||
LMG 0(R8), R5, R6
|
||||
LE_CALL // balr R7, R6 __err2ad (return #2)
|
||||
NOPH
|
||||
MOVW (R3), R2 // retrieve errno2
|
||||
MOVD R2, errno2+40(FP) // store in return area
|
||||
|
||||
done:
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
RET
|
||||
|
||||
//
|
||||
// Call LE function, if the return is 0
|
||||
// errno and errno2 is retrieved
|
||||
//
|
||||
TEXT ·CallLeFuncWithPtrReturn(SB), NOSPLIT, $0
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
MOVD CAA(R8), R9
|
||||
MOVD g, GOCB(R9)
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
|
||||
MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
|
||||
|
||||
MOVD parms_base+8(FP), R7 // R7 -> argument array
|
||||
MOVD parms_len+16(FP), R8 // R8 number of arguments
|
||||
|
||||
// arg 1 ---> R1
|
||||
CMP R8, $0
|
||||
BEQ docall
|
||||
SUB $1, R8
|
||||
MOVD 0(R7), R1
|
||||
|
||||
// arg 2 ---> R2
|
||||
CMP R8, $0
|
||||
BEQ docall
|
||||
SUB $1, R8
|
||||
ADD $8, R7
|
||||
MOVD 0(R7), R2
|
||||
|
||||
// arg 3 --> R3
|
||||
CMP R8, $0
|
||||
BEQ docall
|
||||
SUB $1, R8
|
||||
ADD $8, R7
|
||||
MOVD 0(R7), R3
|
||||
|
||||
CMP R8, $0
|
||||
BEQ docall
|
||||
MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
|
||||
|
||||
repeat:
|
||||
ADD $8, R7
|
||||
MOVD 0(R7), R0 // advance arg pointer by 8 byte
|
||||
ADD $8, R6 // advance LE argument address by 8 byte
|
||||
MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
|
||||
SUB $1, R8
|
||||
CMP R8, $0
|
||||
BNE repeat
|
||||
|
||||
docall:
|
||||
MOVD funcdesc+0(FP), R8 // R8-> function descriptor
|
||||
LMG 0(R8), R5, R6
|
||||
MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
|
||||
LE_CALL // balr R7, R6 (return #1)
|
||||
NOPH
|
||||
MOVD R3, ret+32(FP)
|
||||
CMP R3, $0 // compare result to 0
|
||||
BNE done
|
||||
|
||||
// retrieve errno and errno2
|
||||
MOVD zosLibVec<>(SB), R8
|
||||
ADD $(__errno), R8
|
||||
LMG 0(R8), R5, R6
|
||||
LE_CALL // balr R7, R6 __errno (return #3)
|
||||
NOPH
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+48(FP)
|
||||
MOVD zosLibVec<>(SB), R8
|
||||
ADD $(__err2ad), R8
|
||||
LMG 0(R8), R5, R6
|
||||
LE_CALL // balr R7, R6 __err2ad (return #2)
|
||||
NOPH
|
||||
MOVW (R3), R2 // retrieve errno2
|
||||
MOVD R2, errno2+40(FP) // store in return area
|
||||
XOR R2, R2
|
||||
MOVWZ R2, (R3) // clear errno2
|
||||
|
||||
done:
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
RET
|
||||
|
||||
//
|
||||
// function to test if a pointer can be safely dereferenced (content read)
|
||||
// return 0 for succces
|
||||
//
|
||||
TEXT ·ptrtest(SB), NOSPLIT, $0-16
|
||||
MOVD arg+0(FP), R10 // test pointer in R10
|
||||
|
||||
// set up R2 to point to CEECAADMC
|
||||
BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
|
||||
BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
|
||||
BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
|
||||
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
|
||||
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
|
||||
BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
|
||||
|
||||
// set up R5 to point to the "shunt" path which set 1 to R3 (failure)
|
||||
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
|
||||
BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
|
||||
BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
|
||||
|
||||
// if r3 is not zero (failed) then branch to finish
|
||||
BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
|
||||
BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
|
||||
|
||||
// stomic store shunt address in R5 into CEECAADMC
|
||||
BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
|
||||
|
||||
// now try reading from the test pointer in R10, if it fails it branches to the "lghi" instruction above
|
||||
BYTE $0xE3; BYTE $0x9A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 9,0(10)
|
||||
|
||||
// finish here, restore 0 into CEECAADMC
|
||||
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
|
||||
BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
|
||||
MOVD R3, ret+8(FP) // result in R3
|
||||
RET
|
||||
|
||||
//
|
||||
// function to test if a untptr can be loaded from a pointer
|
||||
// return 1: the 8-byte content
|
||||
// 2: 0 for success, 1 for failure
|
||||
//
|
||||
// func safeload(ptr uintptr) ( value uintptr, error uintptr)
|
||||
TEXT ·safeload(SB), NOSPLIT, $0-24
|
||||
MOVD ptr+0(FP), R10 // test pointer in R10
|
||||
MOVD $0x0, R6
|
||||
BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
|
||||
BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
|
||||
BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
|
||||
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
|
||||
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
|
||||
BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
|
||||
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
|
||||
BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
|
||||
BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
|
||||
BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
|
||||
BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
|
||||
BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
|
||||
BYTE $0xE3; BYTE $0x6A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 6,0(10)
|
||||
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
|
||||
BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
|
||||
MOVD R6, value+8(FP) // result in R6
|
||||
MOVD R3, error+16(FP) // error in R3
|
||||
RET
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// Copyright 2025 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.21 && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos)
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//go:linkname runtime_getAuxv runtime.getAuxv
|
||||
func runtime_getAuxv() []uintptr
|
||||
|
||||
// Auxv returns the ELF auxiliary vector as a sequence of key/value pairs.
|
||||
// The returned slice is always a fresh copy, owned by the caller.
|
||||
// It returns an error on non-ELF platforms, or if the auxiliary vector cannot be accessed,
|
||||
// which happens in some locked-down environments and build modes.
|
||||
func Auxv() ([][2]uintptr, error) {
|
||||
vec := runtime_getAuxv()
|
||||
vecLen := len(vec)
|
||||
|
||||
if vecLen == 0 {
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
|
||||
if vecLen%2 != 0 {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
|
||||
result := make([]uintptr, vecLen)
|
||||
copy(result, vec)
|
||||
return unsafe.Slice((*[2]uintptr)(unsafe.Pointer(&result[0])), vecLen/2), nil
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// Copyright 2025 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.21 && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos)
|
||||
|
||||
package unix
|
||||
|
||||
import "syscall"
|
||||
|
||||
func Auxv() ([][2]uintptr, error) {
|
||||
return nil, syscall.ENOTSUP
|
||||
}
|
||||
+657
@@ -0,0 +1,657 @@
|
||||
// Copyright 2024 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 zos
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//go:noescape
|
||||
func bpxcall(plist []unsafe.Pointer, bpx_offset int64)
|
||||
|
||||
//go:noescape
|
||||
func A2e([]byte)
|
||||
|
||||
//go:noescape
|
||||
func E2a([]byte)
|
||||
|
||||
const (
|
||||
BPX4STA = 192 // stat
|
||||
BPX4FST = 104 // fstat
|
||||
BPX4LST = 132 // lstat
|
||||
BPX4OPN = 156 // open
|
||||
BPX4CLO = 72 // close
|
||||
BPX4CHR = 500 // chattr
|
||||
BPX4FCR = 504 // fchattr
|
||||
BPX4LCR = 1180 // lchattr
|
||||
BPX4CTW = 492 // cond_timed_wait
|
||||
BPX4GTH = 1056 // __getthent
|
||||
BPX4PTQ = 412 // pthread_quiesc
|
||||
BPX4PTR = 320 // ptrace
|
||||
)
|
||||
|
||||
const (
|
||||
//options
|
||||
//byte1
|
||||
BPX_OPNFHIGH = 0x80
|
||||
//byte2
|
||||
BPX_OPNFEXEC = 0x80
|
||||
//byte3
|
||||
BPX_O_NOLARGEFILE = 0x08
|
||||
BPX_O_LARGEFILE = 0x04
|
||||
BPX_O_ASYNCSIG = 0x02
|
||||
BPX_O_SYNC = 0x01
|
||||
//byte4
|
||||
BPX_O_CREXCL = 0xc0
|
||||
BPX_O_CREAT = 0x80
|
||||
BPX_O_EXCL = 0x40
|
||||
BPX_O_NOCTTY = 0x20
|
||||
BPX_O_TRUNC = 0x10
|
||||
BPX_O_APPEND = 0x08
|
||||
BPX_O_NONBLOCK = 0x04
|
||||
BPX_FNDELAY = 0x04
|
||||
BPX_O_RDWR = 0x03
|
||||
BPX_O_RDONLY = 0x02
|
||||
BPX_O_WRONLY = 0x01
|
||||
BPX_O_ACCMODE = 0x03
|
||||
BPX_O_GETFL = 0x0f
|
||||
|
||||
//mode
|
||||
// byte1 (file type)
|
||||
BPX_FT_DIR = 1
|
||||
BPX_FT_CHARSPEC = 2
|
||||
BPX_FT_REGFILE = 3
|
||||
BPX_FT_FIFO = 4
|
||||
BPX_FT_SYMLINK = 5
|
||||
BPX_FT_SOCKET = 6
|
||||
//byte3
|
||||
BPX_S_ISUID = 0x08
|
||||
BPX_S_ISGID = 0x04
|
||||
BPX_S_ISVTX = 0x02
|
||||
BPX_S_IRWXU1 = 0x01
|
||||
BPX_S_IRUSR = 0x01
|
||||
//byte4
|
||||
BPX_S_IRWXU2 = 0xc0
|
||||
BPX_S_IWUSR = 0x80
|
||||
BPX_S_IXUSR = 0x40
|
||||
BPX_S_IRWXG = 0x38
|
||||
BPX_S_IRGRP = 0x20
|
||||
BPX_S_IWGRP = 0x10
|
||||
BPX_S_IXGRP = 0x08
|
||||
BPX_S_IRWXOX = 0x07
|
||||
BPX_S_IROTH = 0x04
|
||||
BPX_S_IWOTH = 0x02
|
||||
BPX_S_IXOTH = 0x01
|
||||
|
||||
CW_INTRPT = 1
|
||||
CW_CONDVAR = 32
|
||||
CW_TIMEOUT = 64
|
||||
|
||||
PGTHA_NEXT = 2
|
||||
PGTHA_CURRENT = 1
|
||||
PGTHA_FIRST = 0
|
||||
PGTHA_LAST = 3
|
||||
PGTHA_PROCESS = 0x80
|
||||
PGTHA_CONTTY = 0x40
|
||||
PGTHA_PATH = 0x20
|
||||
PGTHA_COMMAND = 0x10
|
||||
PGTHA_FILEDATA = 0x08
|
||||
PGTHA_THREAD = 0x04
|
||||
PGTHA_PTAG = 0x02
|
||||
PGTHA_COMMANDLONG = 0x01
|
||||
PGTHA_THREADFAST = 0x80
|
||||
PGTHA_FILEPATH = 0x40
|
||||
PGTHA_THDSIGMASK = 0x20
|
||||
// thread quiece mode
|
||||
QUIESCE_TERM int32 = 1
|
||||
QUIESCE_FORCE int32 = 2
|
||||
QUIESCE_QUERY int32 = 3
|
||||
QUIESCE_FREEZE int32 = 4
|
||||
QUIESCE_UNFREEZE int32 = 5
|
||||
FREEZE_THIS_THREAD int32 = 6
|
||||
FREEZE_EXIT int32 = 8
|
||||
QUIESCE_SRB int32 = 9
|
||||
)
|
||||
|
||||
type Pgtha struct {
|
||||
Pid uint32 // 0
|
||||
Tid0 uint32 // 4
|
||||
Tid1 uint32
|
||||
Accesspid byte // C
|
||||
Accesstid byte // D
|
||||
Accessasid uint16 // E
|
||||
Loginname [8]byte // 10
|
||||
Flag1 byte // 18
|
||||
Flag1b2 byte // 19
|
||||
}
|
||||
|
||||
type Bpxystat_t struct { // DSECT BPXYSTAT
|
||||
St_id [4]uint8 // 0
|
||||
St_length uint16 // 0x4
|
||||
St_version uint16 // 0x6
|
||||
St_mode uint32 // 0x8
|
||||
St_ino uint32 // 0xc
|
||||
St_dev uint32 // 0x10
|
||||
St_nlink uint32 // 0x14
|
||||
St_uid uint32 // 0x18
|
||||
St_gid uint32 // 0x1c
|
||||
St_size uint64 // 0x20
|
||||
St_atime uint32 // 0x28
|
||||
St_mtime uint32 // 0x2c
|
||||
St_ctime uint32 // 0x30
|
||||
St_rdev uint32 // 0x34
|
||||
St_auditoraudit uint32 // 0x38
|
||||
St_useraudit uint32 // 0x3c
|
||||
St_blksize uint32 // 0x40
|
||||
St_createtime uint32 // 0x44
|
||||
St_auditid [4]uint32 // 0x48
|
||||
St_res01 uint32 // 0x58
|
||||
Ft_ccsid uint16 // 0x5c
|
||||
Ft_flags uint16 // 0x5e
|
||||
St_res01a [2]uint32 // 0x60
|
||||
St_res02 uint32 // 0x68
|
||||
St_blocks uint32 // 0x6c
|
||||
St_opaque [3]uint8 // 0x70
|
||||
St_visible uint8 // 0x73
|
||||
St_reftime uint32 // 0x74
|
||||
St_fid uint64 // 0x78
|
||||
St_filefmt uint8 // 0x80
|
||||
St_fspflag2 uint8 // 0x81
|
||||
St_res03 [2]uint8 // 0x82
|
||||
St_ctimemsec uint32 // 0x84
|
||||
St_seclabel [8]uint8 // 0x88
|
||||
St_res04 [4]uint8 // 0x90
|
||||
// end of version 1
|
||||
_ uint32 // 0x94
|
||||
St_atime64 uint64 // 0x98
|
||||
St_mtime64 uint64 // 0xa0
|
||||
St_ctime64 uint64 // 0xa8
|
||||
St_createtime64 uint64 // 0xb0
|
||||
St_reftime64 uint64 // 0xb8
|
||||
_ uint64 // 0xc0
|
||||
St_res05 [16]uint8 // 0xc8
|
||||
// end of version 2
|
||||
}
|
||||
|
||||
type BpxFilestatus struct {
|
||||
Oflag1 byte
|
||||
Oflag2 byte
|
||||
Oflag3 byte
|
||||
Oflag4 byte
|
||||
}
|
||||
|
||||
type BpxMode struct {
|
||||
Ftype byte
|
||||
Mode1 byte
|
||||
Mode2 byte
|
||||
Mode3 byte
|
||||
}
|
||||
|
||||
// Thr attribute structure for extended attributes
|
||||
type Bpxyatt_t struct { // DSECT BPXYATT
|
||||
Att_id [4]uint8
|
||||
Att_version uint16
|
||||
Att_res01 [2]uint8
|
||||
Att_setflags1 uint8
|
||||
Att_setflags2 uint8
|
||||
Att_setflags3 uint8
|
||||
Att_setflags4 uint8
|
||||
Att_mode uint32
|
||||
Att_uid uint32
|
||||
Att_gid uint32
|
||||
Att_opaquemask [3]uint8
|
||||
Att_visblmaskres uint8
|
||||
Att_opaque [3]uint8
|
||||
Att_visibleres uint8
|
||||
Att_size_h uint32
|
||||
Att_size_l uint32
|
||||
Att_atime uint32
|
||||
Att_mtime uint32
|
||||
Att_auditoraudit uint32
|
||||
Att_useraudit uint32
|
||||
Att_ctime uint32
|
||||
Att_reftime uint32
|
||||
// end of version 1
|
||||
Att_filefmt uint8
|
||||
Att_res02 [3]uint8
|
||||
Att_filetag uint32
|
||||
Att_res03 [8]uint8
|
||||
// end of version 2
|
||||
Att_atime64 uint64
|
||||
Att_mtime64 uint64
|
||||
Att_ctime64 uint64
|
||||
Att_reftime64 uint64
|
||||
Att_seclabel [8]uint8
|
||||
Att_ver3res02 [8]uint8
|
||||
// end of version 3
|
||||
}
|
||||
|
||||
func BpxOpen(name string, options *BpxFilestatus, mode *BpxMode) (rv int32, rc int32, rn int32) {
|
||||
if len(name) < 1024 {
|
||||
var namebuf [1024]byte
|
||||
sz := int32(copy(namebuf[:], name))
|
||||
A2e(namebuf[:sz])
|
||||
var parms [7]unsafe.Pointer
|
||||
parms[0] = unsafe.Pointer(&sz)
|
||||
parms[1] = unsafe.Pointer(&namebuf[0])
|
||||
parms[2] = unsafe.Pointer(options)
|
||||
parms[3] = unsafe.Pointer(mode)
|
||||
parms[4] = unsafe.Pointer(&rv)
|
||||
parms[5] = unsafe.Pointer(&rc)
|
||||
parms[6] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4OPN)
|
||||
return rv, rc, rn
|
||||
}
|
||||
return -1, -1, -1
|
||||
}
|
||||
|
||||
func BpxClose(fd int32) (rv int32, rc int32, rn int32) {
|
||||
var parms [4]unsafe.Pointer
|
||||
parms[0] = unsafe.Pointer(&fd)
|
||||
parms[1] = unsafe.Pointer(&rv)
|
||||
parms[2] = unsafe.Pointer(&rc)
|
||||
parms[3] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4CLO)
|
||||
return rv, rc, rn
|
||||
}
|
||||
|
||||
func BpxFileFStat(fd int32, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
|
||||
st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
|
||||
st.St_version = 2
|
||||
stat_sz := uint32(unsafe.Sizeof(*st))
|
||||
var parms [6]unsafe.Pointer
|
||||
parms[0] = unsafe.Pointer(&fd)
|
||||
parms[1] = unsafe.Pointer(&stat_sz)
|
||||
parms[2] = unsafe.Pointer(st)
|
||||
parms[3] = unsafe.Pointer(&rv)
|
||||
parms[4] = unsafe.Pointer(&rc)
|
||||
parms[5] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4FST)
|
||||
return rv, rc, rn
|
||||
}
|
||||
|
||||
func BpxFileStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
|
||||
if len(name) < 1024 {
|
||||
var namebuf [1024]byte
|
||||
sz := int32(copy(namebuf[:], name))
|
||||
A2e(namebuf[:sz])
|
||||
st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
|
||||
st.St_version = 2
|
||||
stat_sz := uint32(unsafe.Sizeof(*st))
|
||||
var parms [7]unsafe.Pointer
|
||||
parms[0] = unsafe.Pointer(&sz)
|
||||
parms[1] = unsafe.Pointer(&namebuf[0])
|
||||
parms[2] = unsafe.Pointer(&stat_sz)
|
||||
parms[3] = unsafe.Pointer(st)
|
||||
parms[4] = unsafe.Pointer(&rv)
|
||||
parms[5] = unsafe.Pointer(&rc)
|
||||
parms[6] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4STA)
|
||||
return rv, rc, rn
|
||||
}
|
||||
return -1, -1, -1
|
||||
}
|
||||
|
||||
func BpxFileLStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
|
||||
if len(name) < 1024 {
|
||||
var namebuf [1024]byte
|
||||
sz := int32(copy(namebuf[:], name))
|
||||
A2e(namebuf[:sz])
|
||||
st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
|
||||
st.St_version = 2
|
||||
stat_sz := uint32(unsafe.Sizeof(*st))
|
||||
var parms [7]unsafe.Pointer
|
||||
parms[0] = unsafe.Pointer(&sz)
|
||||
parms[1] = unsafe.Pointer(&namebuf[0])
|
||||
parms[2] = unsafe.Pointer(&stat_sz)
|
||||
parms[3] = unsafe.Pointer(st)
|
||||
parms[4] = unsafe.Pointer(&rv)
|
||||
parms[5] = unsafe.Pointer(&rc)
|
||||
parms[6] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4LST)
|
||||
return rv, rc, rn
|
||||
}
|
||||
return -1, -1, -1
|
||||
}
|
||||
|
||||
func BpxChattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
|
||||
if len(path) >= 1024 {
|
||||
return -1, -1, -1
|
||||
}
|
||||
var namebuf [1024]byte
|
||||
sz := int32(copy(namebuf[:], path))
|
||||
A2e(namebuf[:sz])
|
||||
attr_sz := uint32(unsafe.Sizeof(*attr))
|
||||
var parms [7]unsafe.Pointer
|
||||
parms[0] = unsafe.Pointer(&sz)
|
||||
parms[1] = unsafe.Pointer(&namebuf[0])
|
||||
parms[2] = unsafe.Pointer(&attr_sz)
|
||||
parms[3] = unsafe.Pointer(attr)
|
||||
parms[4] = unsafe.Pointer(&rv)
|
||||
parms[5] = unsafe.Pointer(&rc)
|
||||
parms[6] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4CHR)
|
||||
return rv, rc, rn
|
||||
}
|
||||
|
||||
func BpxLchattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
|
||||
if len(path) >= 1024 {
|
||||
return -1, -1, -1
|
||||
}
|
||||
var namebuf [1024]byte
|
||||
sz := int32(copy(namebuf[:], path))
|
||||
A2e(namebuf[:sz])
|
||||
attr_sz := uint32(unsafe.Sizeof(*attr))
|
||||
var parms [7]unsafe.Pointer
|
||||
parms[0] = unsafe.Pointer(&sz)
|
||||
parms[1] = unsafe.Pointer(&namebuf[0])
|
||||
parms[2] = unsafe.Pointer(&attr_sz)
|
||||
parms[3] = unsafe.Pointer(attr)
|
||||
parms[4] = unsafe.Pointer(&rv)
|
||||
parms[5] = unsafe.Pointer(&rc)
|
||||
parms[6] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4LCR)
|
||||
return rv, rc, rn
|
||||
}
|
||||
|
||||
func BpxFchattr(fd int32, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
|
||||
attr_sz := uint32(unsafe.Sizeof(*attr))
|
||||
var parms [6]unsafe.Pointer
|
||||
parms[0] = unsafe.Pointer(&fd)
|
||||
parms[1] = unsafe.Pointer(&attr_sz)
|
||||
parms[2] = unsafe.Pointer(attr)
|
||||
parms[3] = unsafe.Pointer(&rv)
|
||||
parms[4] = unsafe.Pointer(&rc)
|
||||
parms[5] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4FCR)
|
||||
return rv, rc, rn
|
||||
}
|
||||
|
||||
func BpxCondTimedWait(sec uint32, nsec uint32, events uint32, secrem *uint32, nsecrem *uint32) (rv int32, rc int32, rn int32) {
|
||||
var parms [8]unsafe.Pointer
|
||||
parms[0] = unsafe.Pointer(&sec)
|
||||
parms[1] = unsafe.Pointer(&nsec)
|
||||
parms[2] = unsafe.Pointer(&events)
|
||||
parms[3] = unsafe.Pointer(secrem)
|
||||
parms[4] = unsafe.Pointer(nsecrem)
|
||||
parms[5] = unsafe.Pointer(&rv)
|
||||
parms[6] = unsafe.Pointer(&rc)
|
||||
parms[7] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4CTW)
|
||||
return rv, rc, rn
|
||||
}
|
||||
func BpxGetthent(in *Pgtha, outlen *uint32, out unsafe.Pointer) (rv int32, rc int32, rn int32) {
|
||||
var parms [7]unsafe.Pointer
|
||||
inlen := uint32(26) // nothing else will work. Go says Pgtha is 28-byte because of alignment, but Pgtha is "packed" and must be 26-byte
|
||||
parms[0] = unsafe.Pointer(&inlen)
|
||||
parms[1] = unsafe.Pointer(&in)
|
||||
parms[2] = unsafe.Pointer(outlen)
|
||||
parms[3] = unsafe.Pointer(&out)
|
||||
parms[4] = unsafe.Pointer(&rv)
|
||||
parms[5] = unsafe.Pointer(&rc)
|
||||
parms[6] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4GTH)
|
||||
return rv, rc, rn
|
||||
}
|
||||
func ZosJobname() (jobname string, err error) {
|
||||
var pgtha Pgtha
|
||||
pgtha.Pid = uint32(Getpid())
|
||||
pgtha.Accesspid = PGTHA_CURRENT
|
||||
pgtha.Flag1 = PGTHA_PROCESS
|
||||
var out [256]byte
|
||||
var outlen uint32
|
||||
outlen = 256
|
||||
rv, rc, rn := BpxGetthent(&pgtha, &outlen, unsafe.Pointer(&out[0]))
|
||||
if rv == 0 {
|
||||
gthc := []byte{0x87, 0xa3, 0x88, 0x83} // 'gthc' in ebcdic
|
||||
ix := bytes.Index(out[:], gthc)
|
||||
if ix == -1 {
|
||||
err = fmt.Errorf("BPX4GTH: gthc return data not found")
|
||||
return
|
||||
}
|
||||
jn := out[ix+80 : ix+88] // we didn't declare Pgthc, but jobname is 8-byte at offset 80
|
||||
E2a(jn)
|
||||
jobname = string(bytes.TrimRight(jn, " "))
|
||||
|
||||
} else {
|
||||
err = fmt.Errorf("BPX4GTH: rc=%d errno=%d reason=code=0x%x", rv, rc, rn)
|
||||
}
|
||||
return
|
||||
}
|
||||
func Bpx4ptq(code int32, data string) (rv int32, rc int32, rn int32) {
|
||||
var userdata [8]byte
|
||||
var parms [5]unsafe.Pointer
|
||||
copy(userdata[:], data+" ")
|
||||
A2e(userdata[:])
|
||||
parms[0] = unsafe.Pointer(&code)
|
||||
parms[1] = unsafe.Pointer(&userdata[0])
|
||||
parms[2] = unsafe.Pointer(&rv)
|
||||
parms[3] = unsafe.Pointer(&rc)
|
||||
parms[4] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4PTQ)
|
||||
return rv, rc, rn
|
||||
}
|
||||
|
||||
const (
|
||||
PT_TRACE_ME = 0 // Debug this process
|
||||
PT_READ_I = 1 // Read a full word
|
||||
PT_READ_D = 2 // Read a full word
|
||||
PT_READ_U = 3 // Read control info
|
||||
PT_WRITE_I = 4 //Write a full word
|
||||
PT_WRITE_D = 5 //Write a full word
|
||||
PT_CONTINUE = 7 //Continue the process
|
||||
PT_KILL = 8 //Terminate the process
|
||||
PT_READ_GPR = 11 // Read GPR, CR, PSW
|
||||
PT_READ_FPR = 12 // Read FPR
|
||||
PT_READ_VR = 13 // Read VR
|
||||
PT_WRITE_GPR = 14 // Write GPR, CR, PSW
|
||||
PT_WRITE_FPR = 15 // Write FPR
|
||||
PT_WRITE_VR = 16 // Write VR
|
||||
PT_READ_BLOCK = 17 // Read storage
|
||||
PT_WRITE_BLOCK = 19 // Write storage
|
||||
PT_READ_GPRH = 20 // Read GPRH
|
||||
PT_WRITE_GPRH = 21 // Write GPRH
|
||||
PT_REGHSET = 22 // Read all GPRHs
|
||||
PT_ATTACH = 30 // Attach to a process
|
||||
PT_DETACH = 31 // Detach from a process
|
||||
PT_REGSET = 32 // Read all GPRs
|
||||
PT_REATTACH = 33 // Reattach to a process
|
||||
PT_LDINFO = 34 // Read loader info
|
||||
PT_MULTI = 35 // Multi process mode
|
||||
PT_LD64INFO = 36 // RMODE64 Info Area
|
||||
PT_BLOCKREQ = 40 // Block request
|
||||
PT_THREAD_INFO = 60 // Read thread info
|
||||
PT_THREAD_MODIFY = 61
|
||||
PT_THREAD_READ_FOCUS = 62
|
||||
PT_THREAD_WRITE_FOCUS = 63
|
||||
PT_THREAD_HOLD = 64
|
||||
PT_THREAD_SIGNAL = 65
|
||||
PT_EXPLAIN = 66
|
||||
PT_EVENTS = 67
|
||||
PT_THREAD_INFO_EXTENDED = 68
|
||||
PT_REATTACH2 = 71
|
||||
PT_CAPTURE = 72
|
||||
PT_UNCAPTURE = 73
|
||||
PT_GET_THREAD_TCB = 74
|
||||
PT_GET_ALET = 75
|
||||
PT_SWAPIN = 76
|
||||
PT_EXTENDED_EVENT = 98
|
||||
PT_RECOVER = 99 // Debug a program check
|
||||
PT_GPR0 = 0 // General purpose register 0
|
||||
PT_GPR1 = 1 // General purpose register 1
|
||||
PT_GPR2 = 2 // General purpose register 2
|
||||
PT_GPR3 = 3 // General purpose register 3
|
||||
PT_GPR4 = 4 // General purpose register 4
|
||||
PT_GPR5 = 5 // General purpose register 5
|
||||
PT_GPR6 = 6 // General purpose register 6
|
||||
PT_GPR7 = 7 // General purpose register 7
|
||||
PT_GPR8 = 8 // General purpose register 8
|
||||
PT_GPR9 = 9 // General purpose register 9
|
||||
PT_GPR10 = 10 // General purpose register 10
|
||||
PT_GPR11 = 11 // General purpose register 11
|
||||
PT_GPR12 = 12 // General purpose register 12
|
||||
PT_GPR13 = 13 // General purpose register 13
|
||||
PT_GPR14 = 14 // General purpose register 14
|
||||
PT_GPR15 = 15 // General purpose register 15
|
||||
PT_FPR0 = 16 // Floating point register 0
|
||||
PT_FPR1 = 17 // Floating point register 1
|
||||
PT_FPR2 = 18 // Floating point register 2
|
||||
PT_FPR3 = 19 // Floating point register 3
|
||||
PT_FPR4 = 20 // Floating point register 4
|
||||
PT_FPR5 = 21 // Floating point register 5
|
||||
PT_FPR6 = 22 // Floating point register 6
|
||||
PT_FPR7 = 23 // Floating point register 7
|
||||
PT_FPR8 = 24 // Floating point register 8
|
||||
PT_FPR9 = 25 // Floating point register 9
|
||||
PT_FPR10 = 26 // Floating point register 10
|
||||
PT_FPR11 = 27 // Floating point register 11
|
||||
PT_FPR12 = 28 // Floating point register 12
|
||||
PT_FPR13 = 29 // Floating point register 13
|
||||
PT_FPR14 = 30 // Floating point register 14
|
||||
PT_FPR15 = 31 // Floating point register 15
|
||||
PT_FPC = 32 // Floating point control register
|
||||
PT_PSW = 40 // PSW
|
||||
PT_PSW0 = 40 // Left half of the PSW
|
||||
PT_PSW1 = 41 // Right half of the PSW
|
||||
PT_CR0 = 42 // Control register 0
|
||||
PT_CR1 = 43 // Control register 1
|
||||
PT_CR2 = 44 // Control register 2
|
||||
PT_CR3 = 45 // Control register 3
|
||||
PT_CR4 = 46 // Control register 4
|
||||
PT_CR5 = 47 // Control register 5
|
||||
PT_CR6 = 48 // Control register 6
|
||||
PT_CR7 = 49 // Control register 7
|
||||
PT_CR8 = 50 // Control register 8
|
||||
PT_CR9 = 51 // Control register 9
|
||||
PT_CR10 = 52 // Control register 10
|
||||
PT_CR11 = 53 // Control register 11
|
||||
PT_CR12 = 54 // Control register 12
|
||||
PT_CR13 = 55 // Control register 13
|
||||
PT_CR14 = 56 // Control register 14
|
||||
PT_CR15 = 57 // Control register 15
|
||||
PT_GPRH0 = 58 // GP High register 0
|
||||
PT_GPRH1 = 59 // GP High register 1
|
||||
PT_GPRH2 = 60 // GP High register 2
|
||||
PT_GPRH3 = 61 // GP High register 3
|
||||
PT_GPRH4 = 62 // GP High register 4
|
||||
PT_GPRH5 = 63 // GP High register 5
|
||||
PT_GPRH6 = 64 // GP High register 6
|
||||
PT_GPRH7 = 65 // GP High register 7
|
||||
PT_GPRH8 = 66 // GP High register 8
|
||||
PT_GPRH9 = 67 // GP High register 9
|
||||
PT_GPRH10 = 68 // GP High register 10
|
||||
PT_GPRH11 = 69 // GP High register 11
|
||||
PT_GPRH12 = 70 // GP High register 12
|
||||
PT_GPRH13 = 71 // GP High register 13
|
||||
PT_GPRH14 = 72 // GP High register 14
|
||||
PT_GPRH15 = 73 // GP High register 15
|
||||
PT_VR0 = 74 // Vector register 0
|
||||
PT_VR1 = 75 // Vector register 1
|
||||
PT_VR2 = 76 // Vector register 2
|
||||
PT_VR3 = 77 // Vector register 3
|
||||
PT_VR4 = 78 // Vector register 4
|
||||
PT_VR5 = 79 // Vector register 5
|
||||
PT_VR6 = 80 // Vector register 6
|
||||
PT_VR7 = 81 // Vector register 7
|
||||
PT_VR8 = 82 // Vector register 8
|
||||
PT_VR9 = 83 // Vector register 9
|
||||
PT_VR10 = 84 // Vector register 10
|
||||
PT_VR11 = 85 // Vector register 11
|
||||
PT_VR12 = 86 // Vector register 12
|
||||
PT_VR13 = 87 // Vector register 13
|
||||
PT_VR14 = 88 // Vector register 14
|
||||
PT_VR15 = 89 // Vector register 15
|
||||
PT_VR16 = 90 // Vector register 16
|
||||
PT_VR17 = 91 // Vector register 17
|
||||
PT_VR18 = 92 // Vector register 18
|
||||
PT_VR19 = 93 // Vector register 19
|
||||
PT_VR20 = 94 // Vector register 20
|
||||
PT_VR21 = 95 // Vector register 21
|
||||
PT_VR22 = 96 // Vector register 22
|
||||
PT_VR23 = 97 // Vector register 23
|
||||
PT_VR24 = 98 // Vector register 24
|
||||
PT_VR25 = 99 // Vector register 25
|
||||
PT_VR26 = 100 // Vector register 26
|
||||
PT_VR27 = 101 // Vector register 27
|
||||
PT_VR28 = 102 // Vector register 28
|
||||
PT_VR29 = 103 // Vector register 29
|
||||
PT_VR30 = 104 // Vector register 30
|
||||
PT_VR31 = 105 // Vector register 31
|
||||
PT_PSWG = 106 // PSWG
|
||||
PT_PSWG0 = 106 // Bytes 0-3
|
||||
PT_PSWG1 = 107 // Bytes 4-7
|
||||
PT_PSWG2 = 108 // Bytes 8-11 (IA high word)
|
||||
PT_PSWG3 = 109 // Bytes 12-15 (IA low word)
|
||||
)
|
||||
|
||||
func Bpx4ptr(request int32, pid int32, addr unsafe.Pointer, data unsafe.Pointer, buffer unsafe.Pointer) (rv int32, rc int32, rn int32) {
|
||||
var parms [8]unsafe.Pointer
|
||||
parms[0] = unsafe.Pointer(&request)
|
||||
parms[1] = unsafe.Pointer(&pid)
|
||||
parms[2] = unsafe.Pointer(&addr)
|
||||
parms[3] = unsafe.Pointer(&data)
|
||||
parms[4] = unsafe.Pointer(&buffer)
|
||||
parms[5] = unsafe.Pointer(&rv)
|
||||
parms[6] = unsafe.Pointer(&rc)
|
||||
parms[7] = unsafe.Pointer(&rn)
|
||||
bpxcall(parms[:], BPX4PTR)
|
||||
return rv, rc, rn
|
||||
}
|
||||
|
||||
func copyU8(val uint8, dest []uint8) int {
|
||||
if len(dest) < 1 {
|
||||
return 0
|
||||
}
|
||||
dest[0] = val
|
||||
return 1
|
||||
}
|
||||
|
||||
func copyU8Arr(src, dest []uint8) int {
|
||||
if len(dest) < len(src) {
|
||||
return 0
|
||||
}
|
||||
for i, v := range src {
|
||||
dest[i] = v
|
||||
}
|
||||
return len(src)
|
||||
}
|
||||
|
||||
func copyU16(val uint16, dest []uint16) int {
|
||||
if len(dest) < 1 {
|
||||
return 0
|
||||
}
|
||||
dest[0] = val
|
||||
return 1
|
||||
}
|
||||
|
||||
func copyU32(val uint32, dest []uint32) int {
|
||||
if len(dest) < 1 {
|
||||
return 0
|
||||
}
|
||||
dest[0] = val
|
||||
return 1
|
||||
}
|
||||
|
||||
func copyU32Arr(src, dest []uint32) int {
|
||||
if len(dest) < len(src) {
|
||||
return 0
|
||||
}
|
||||
for i, v := range src {
|
||||
dest[i] = v
|
||||
}
|
||||
return len(src)
|
||||
}
|
||||
|
||||
func copyU64(val uint64, dest []uint64) int {
|
||||
if len(dest) < 1 {
|
||||
return 0
|
||||
}
|
||||
dest[0] = val
|
||||
return 1
|
||||
}
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "go_asm.h"
|
||||
#include "textflag.h"
|
||||
|
||||
// function to call USS assembly language services
|
||||
//
|
||||
// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bit64env.htm
|
||||
//
|
||||
// arg1 unsafe.Pointer array that ressembles an OS PLIST
|
||||
//
|
||||
// arg2 function offset as in
|
||||
// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bpx2cr_List_of_offsets.htm
|
||||
//
|
||||
// func bpxcall(plist []unsafe.Pointer, bpx_offset int64)
|
||||
|
||||
TEXT ·bpxcall(SB), NOSPLIT|NOFRAME, $0
|
||||
MOVD plist_base+0(FP), R1 // r1 points to plist
|
||||
MOVD bpx_offset+24(FP), R2 // r2 offset to BPX vector table
|
||||
MOVD R14, R7 // save r14
|
||||
MOVD R15, R8 // save r15
|
||||
MOVWZ 16(R0), R9
|
||||
MOVWZ 544(R9), R9
|
||||
MOVWZ 24(R9), R9 // call vector in r9
|
||||
ADD R2, R9 // add offset to vector table
|
||||
MOVWZ (R9), R9 // r9 points to entry point
|
||||
BYTE $0x0D // BL R14,R9 --> basr r14,r9
|
||||
BYTE $0xE9 // clobbers 0,1,14,15
|
||||
MOVD R8, R15 // restore 15
|
||||
JMP R7 // return via saved return address
|
||||
|
||||
// func A2e(arr [] byte)
|
||||
// code page conversion from 819 to 1047
|
||||
TEXT ·A2e(SB), NOSPLIT|NOFRAME, $0
|
||||
MOVD arg_base+0(FP), R2 // pointer to arry of characters
|
||||
MOVD arg_len+8(FP), R3 // count
|
||||
XOR R0, R0
|
||||
XOR R1, R1
|
||||
BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2))
|
||||
|
||||
// ASCII -> EBCDIC conversion table:
|
||||
BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03
|
||||
BYTE $0x37; BYTE $0x2d; BYTE $0x2e; BYTE $0x2f
|
||||
BYTE $0x16; BYTE $0x05; BYTE $0x15; BYTE $0x0b
|
||||
BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f
|
||||
BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13
|
||||
BYTE $0x3c; BYTE $0x3d; BYTE $0x32; BYTE $0x26
|
||||
BYTE $0x18; BYTE $0x19; BYTE $0x3f; BYTE $0x27
|
||||
BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f
|
||||
BYTE $0x40; BYTE $0x5a; BYTE $0x7f; BYTE $0x7b
|
||||
BYTE $0x5b; BYTE $0x6c; BYTE $0x50; BYTE $0x7d
|
||||
BYTE $0x4d; BYTE $0x5d; BYTE $0x5c; BYTE $0x4e
|
||||
BYTE $0x6b; BYTE $0x60; BYTE $0x4b; BYTE $0x61
|
||||
BYTE $0xf0; BYTE $0xf1; BYTE $0xf2; BYTE $0xf3
|
||||
BYTE $0xf4; BYTE $0xf5; BYTE $0xf6; BYTE $0xf7
|
||||
BYTE $0xf8; BYTE $0xf9; BYTE $0x7a; BYTE $0x5e
|
||||
BYTE $0x4c; BYTE $0x7e; BYTE $0x6e; BYTE $0x6f
|
||||
BYTE $0x7c; BYTE $0xc1; BYTE $0xc2; BYTE $0xc3
|
||||
BYTE $0xc4; BYTE $0xc5; BYTE $0xc6; BYTE $0xc7
|
||||
BYTE $0xc8; BYTE $0xc9; BYTE $0xd1; BYTE $0xd2
|
||||
BYTE $0xd3; BYTE $0xd4; BYTE $0xd5; BYTE $0xd6
|
||||
BYTE $0xd7; BYTE $0xd8; BYTE $0xd9; BYTE $0xe2
|
||||
BYTE $0xe3; BYTE $0xe4; BYTE $0xe5; BYTE $0xe6
|
||||
BYTE $0xe7; BYTE $0xe8; BYTE $0xe9; BYTE $0xad
|
||||
BYTE $0xe0; BYTE $0xbd; BYTE $0x5f; BYTE $0x6d
|
||||
BYTE $0x79; BYTE $0x81; BYTE $0x82; BYTE $0x83
|
||||
BYTE $0x84; BYTE $0x85; BYTE $0x86; BYTE $0x87
|
||||
BYTE $0x88; BYTE $0x89; BYTE $0x91; BYTE $0x92
|
||||
BYTE $0x93; BYTE $0x94; BYTE $0x95; BYTE $0x96
|
||||
BYTE $0x97; BYTE $0x98; BYTE $0x99; BYTE $0xa2
|
||||
BYTE $0xa3; BYTE $0xa4; BYTE $0xa5; BYTE $0xa6
|
||||
BYTE $0xa7; BYTE $0xa8; BYTE $0xa9; BYTE $0xc0
|
||||
BYTE $0x4f; BYTE $0xd0; BYTE $0xa1; BYTE $0x07
|
||||
BYTE $0x20; BYTE $0x21; BYTE $0x22; BYTE $0x23
|
||||
BYTE $0x24; BYTE $0x25; BYTE $0x06; BYTE $0x17
|
||||
BYTE $0x28; BYTE $0x29; BYTE $0x2a; BYTE $0x2b
|
||||
BYTE $0x2c; BYTE $0x09; BYTE $0x0a; BYTE $0x1b
|
||||
BYTE $0x30; BYTE $0x31; BYTE $0x1a; BYTE $0x33
|
||||
BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x08
|
||||
BYTE $0x38; BYTE $0x39; BYTE $0x3a; BYTE $0x3b
|
||||
BYTE $0x04; BYTE $0x14; BYTE $0x3e; BYTE $0xff
|
||||
BYTE $0x41; BYTE $0xaa; BYTE $0x4a; BYTE $0xb1
|
||||
BYTE $0x9f; BYTE $0xb2; BYTE $0x6a; BYTE $0xb5
|
||||
BYTE $0xbb; BYTE $0xb4; BYTE $0x9a; BYTE $0x8a
|
||||
BYTE $0xb0; BYTE $0xca; BYTE $0xaf; BYTE $0xbc
|
||||
BYTE $0x90; BYTE $0x8f; BYTE $0xea; BYTE $0xfa
|
||||
BYTE $0xbe; BYTE $0xa0; BYTE $0xb6; BYTE $0xb3
|
||||
BYTE $0x9d; BYTE $0xda; BYTE $0x9b; BYTE $0x8b
|
||||
BYTE $0xb7; BYTE $0xb8; BYTE $0xb9; BYTE $0xab
|
||||
BYTE $0x64; BYTE $0x65; BYTE $0x62; BYTE $0x66
|
||||
BYTE $0x63; BYTE $0x67; BYTE $0x9e; BYTE $0x68
|
||||
BYTE $0x74; BYTE $0x71; BYTE $0x72; BYTE $0x73
|
||||
BYTE $0x78; BYTE $0x75; BYTE $0x76; BYTE $0x77
|
||||
BYTE $0xac; BYTE $0x69; BYTE $0xed; BYTE $0xee
|
||||
BYTE $0xeb; BYTE $0xef; BYTE $0xec; BYTE $0xbf
|
||||
BYTE $0x80; BYTE $0xfd; BYTE $0xfe; BYTE $0xfb
|
||||
BYTE $0xfc; BYTE $0xba; BYTE $0xae; BYTE $0x59
|
||||
BYTE $0x44; BYTE $0x45; BYTE $0x42; BYTE $0x46
|
||||
BYTE $0x43; BYTE $0x47; BYTE $0x9c; BYTE $0x48
|
||||
BYTE $0x54; BYTE $0x51; BYTE $0x52; BYTE $0x53
|
||||
BYTE $0x58; BYTE $0x55; BYTE $0x56; BYTE $0x57
|
||||
BYTE $0x8c; BYTE $0x49; BYTE $0xcd; BYTE $0xce
|
||||
BYTE $0xcb; BYTE $0xcf; BYTE $0xcc; BYTE $0xe1
|
||||
BYTE $0x70; BYTE $0xdd; BYTE $0xde; BYTE $0xdb
|
||||
BYTE $0xdc; BYTE $0x8d; BYTE $0x8e; BYTE $0xdf
|
||||
|
||||
retry:
|
||||
WORD $0xB9931022 // TROO 2,2,b'0001'
|
||||
BVS retry
|
||||
RET
|
||||
|
||||
// func e2a(arr [] byte)
|
||||
// code page conversion from 1047 to 819
|
||||
TEXT ·E2a(SB), NOSPLIT|NOFRAME, $0
|
||||
MOVD arg_base+0(FP), R2 // pointer to arry of characters
|
||||
MOVD arg_len+8(FP), R3 // count
|
||||
XOR R0, R0
|
||||
XOR R1, R1
|
||||
BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2))
|
||||
|
||||
// EBCDIC -> ASCII conversion table:
|
||||
BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03
|
||||
BYTE $0x9c; BYTE $0x09; BYTE $0x86; BYTE $0x7f
|
||||
BYTE $0x97; BYTE $0x8d; BYTE $0x8e; BYTE $0x0b
|
||||
BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f
|
||||
BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13
|
||||
BYTE $0x9d; BYTE $0x0a; BYTE $0x08; BYTE $0x87
|
||||
BYTE $0x18; BYTE $0x19; BYTE $0x92; BYTE $0x8f
|
||||
BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f
|
||||
BYTE $0x80; BYTE $0x81; BYTE $0x82; BYTE $0x83
|
||||
BYTE $0x84; BYTE $0x85; BYTE $0x17; BYTE $0x1b
|
||||
BYTE $0x88; BYTE $0x89; BYTE $0x8a; BYTE $0x8b
|
||||
BYTE $0x8c; BYTE $0x05; BYTE $0x06; BYTE $0x07
|
||||
BYTE $0x90; BYTE $0x91; BYTE $0x16; BYTE $0x93
|
||||
BYTE $0x94; BYTE $0x95; BYTE $0x96; BYTE $0x04
|
||||
BYTE $0x98; BYTE $0x99; BYTE $0x9a; BYTE $0x9b
|
||||
BYTE $0x14; BYTE $0x15; BYTE $0x9e; BYTE $0x1a
|
||||
BYTE $0x20; BYTE $0xa0; BYTE $0xe2; BYTE $0xe4
|
||||
BYTE $0xe0; BYTE $0xe1; BYTE $0xe3; BYTE $0xe5
|
||||
BYTE $0xe7; BYTE $0xf1; BYTE $0xa2; BYTE $0x2e
|
||||
BYTE $0x3c; BYTE $0x28; BYTE $0x2b; BYTE $0x7c
|
||||
BYTE $0x26; BYTE $0xe9; BYTE $0xea; BYTE $0xeb
|
||||
BYTE $0xe8; BYTE $0xed; BYTE $0xee; BYTE $0xef
|
||||
BYTE $0xec; BYTE $0xdf; BYTE $0x21; BYTE $0x24
|
||||
BYTE $0x2a; BYTE $0x29; BYTE $0x3b; BYTE $0x5e
|
||||
BYTE $0x2d; BYTE $0x2f; BYTE $0xc2; BYTE $0xc4
|
||||
BYTE $0xc0; BYTE $0xc1; BYTE $0xc3; BYTE $0xc5
|
||||
BYTE $0xc7; BYTE $0xd1; BYTE $0xa6; BYTE $0x2c
|
||||
BYTE $0x25; BYTE $0x5f; BYTE $0x3e; BYTE $0x3f
|
||||
BYTE $0xf8; BYTE $0xc9; BYTE $0xca; BYTE $0xcb
|
||||
BYTE $0xc8; BYTE $0xcd; BYTE $0xce; BYTE $0xcf
|
||||
BYTE $0xcc; BYTE $0x60; BYTE $0x3a; BYTE $0x23
|
||||
BYTE $0x40; BYTE $0x27; BYTE $0x3d; BYTE $0x22
|
||||
BYTE $0xd8; BYTE $0x61; BYTE $0x62; BYTE $0x63
|
||||
BYTE $0x64; BYTE $0x65; BYTE $0x66; BYTE $0x67
|
||||
BYTE $0x68; BYTE $0x69; BYTE $0xab; BYTE $0xbb
|
||||
BYTE $0xf0; BYTE $0xfd; BYTE $0xfe; BYTE $0xb1
|
||||
BYTE $0xb0; BYTE $0x6a; BYTE $0x6b; BYTE $0x6c
|
||||
BYTE $0x6d; BYTE $0x6e; BYTE $0x6f; BYTE $0x70
|
||||
BYTE $0x71; BYTE $0x72; BYTE $0xaa; BYTE $0xba
|
||||
BYTE $0xe6; BYTE $0xb8; BYTE $0xc6; BYTE $0xa4
|
||||
BYTE $0xb5; BYTE $0x7e; BYTE $0x73; BYTE $0x74
|
||||
BYTE $0x75; BYTE $0x76; BYTE $0x77; BYTE $0x78
|
||||
BYTE $0x79; BYTE $0x7a; BYTE $0xa1; BYTE $0xbf
|
||||
BYTE $0xd0; BYTE $0x5b; BYTE $0xde; BYTE $0xae
|
||||
BYTE $0xac; BYTE $0xa3; BYTE $0xa5; BYTE $0xb7
|
||||
BYTE $0xa9; BYTE $0xa7; BYTE $0xb6; BYTE $0xbc
|
||||
BYTE $0xbd; BYTE $0xbe; BYTE $0xdd; BYTE $0xa8
|
||||
BYTE $0xaf; BYTE $0x5d; BYTE $0xb4; BYTE $0xd7
|
||||
BYTE $0x7b; BYTE $0x41; BYTE $0x42; BYTE $0x43
|
||||
BYTE $0x44; BYTE $0x45; BYTE $0x46; BYTE $0x47
|
||||
BYTE $0x48; BYTE $0x49; BYTE $0xad; BYTE $0xf4
|
||||
BYTE $0xf6; BYTE $0xf2; BYTE $0xf3; BYTE $0xf5
|
||||
BYTE $0x7d; BYTE $0x4a; BYTE $0x4b; BYTE $0x4c
|
||||
BYTE $0x4d; BYTE $0x4e; BYTE $0x4f; BYTE $0x50
|
||||
BYTE $0x51; BYTE $0x52; BYTE $0xb9; BYTE $0xfb
|
||||
BYTE $0xfc; BYTE $0xf9; BYTE $0xfa; BYTE $0xff
|
||||
BYTE $0x5c; BYTE $0xf7; BYTE $0x53; BYTE $0x54
|
||||
BYTE $0x55; BYTE $0x56; BYTE $0x57; BYTE $0x58
|
||||
BYTE $0x59; BYTE $0x5a; BYTE $0xb2; BYTE $0xd4
|
||||
BYTE $0xd6; BYTE $0xd2; BYTE $0xd3; BYTE $0xd5
|
||||
BYTE $0x30; BYTE $0x31; BYTE $0x32; BYTE $0x33
|
||||
BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x37
|
||||
BYTE $0x38; BYTE $0x39; BYTE $0xb3; BYTE $0xdb
|
||||
BYTE $0xdc; BYTE $0xd9; BYTE $0xda; BYTE $0x9f
|
||||
|
||||
retry:
|
||||
WORD $0xB9931022 // TROO 2,2,b'0001'
|
||||
BVS retry
|
||||
RET
|
||||
-220
@@ -1,220 +0,0 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// This file simulates epoll on z/OS using poll.
|
||||
|
||||
// Analogous to epoll_event on Linux.
|
||||
// TODO(neeilan): Pad is because the Linux kernel expects a 96-bit struct. We never pass this to the kernel; remove?
|
||||
type EpollEvent struct {
|
||||
Events uint32
|
||||
Fd int32
|
||||
Pad int32
|
||||
}
|
||||
|
||||
const (
|
||||
EPOLLERR = 0x8
|
||||
EPOLLHUP = 0x10
|
||||
EPOLLIN = 0x1
|
||||
EPOLLMSG = 0x400
|
||||
EPOLLOUT = 0x4
|
||||
EPOLLPRI = 0x2
|
||||
EPOLLRDBAND = 0x80
|
||||
EPOLLRDNORM = 0x40
|
||||
EPOLLWRBAND = 0x200
|
||||
EPOLLWRNORM = 0x100
|
||||
EPOLL_CTL_ADD = 0x1
|
||||
EPOLL_CTL_DEL = 0x2
|
||||
EPOLL_CTL_MOD = 0x3
|
||||
// The following constants are part of the epoll API, but represent
|
||||
// currently unsupported functionality on z/OS.
|
||||
// EPOLL_CLOEXEC = 0x80000
|
||||
// EPOLLET = 0x80000000
|
||||
// EPOLLONESHOT = 0x40000000
|
||||
// EPOLLRDHUP = 0x2000 // Typically used with edge-triggered notis
|
||||
// EPOLLEXCLUSIVE = 0x10000000 // Exclusive wake-up mode
|
||||
// EPOLLWAKEUP = 0x20000000 // Relies on Linux's BLOCK_SUSPEND capability
|
||||
)
|
||||
|
||||
// TODO(neeilan): We can eliminate these epToPoll / pToEpoll calls by using identical mask values for POLL/EPOLL
|
||||
// constants where possible The lower 16 bits of epoll events (uint32) can fit any system poll event (int16).
|
||||
|
||||
// epToPollEvt converts epoll event field to poll equivalent.
|
||||
// In epoll, Events is a 32-bit field, while poll uses 16 bits.
|
||||
func epToPollEvt(events uint32) int16 {
|
||||
var ep2p = map[uint32]int16{
|
||||
EPOLLIN: POLLIN,
|
||||
EPOLLOUT: POLLOUT,
|
||||
EPOLLHUP: POLLHUP,
|
||||
EPOLLPRI: POLLPRI,
|
||||
EPOLLERR: POLLERR,
|
||||
}
|
||||
|
||||
var pollEvts int16 = 0
|
||||
for epEvt, pEvt := range ep2p {
|
||||
if (events & epEvt) != 0 {
|
||||
pollEvts |= pEvt
|
||||
}
|
||||
}
|
||||
|
||||
return pollEvts
|
||||
}
|
||||
|
||||
// pToEpollEvt converts 16 bit poll event bitfields to 32-bit epoll event fields.
|
||||
func pToEpollEvt(revents int16) uint32 {
|
||||
var p2ep = map[int16]uint32{
|
||||
POLLIN: EPOLLIN,
|
||||
POLLOUT: EPOLLOUT,
|
||||
POLLHUP: EPOLLHUP,
|
||||
POLLPRI: EPOLLPRI,
|
||||
POLLERR: EPOLLERR,
|
||||
}
|
||||
|
||||
var epollEvts uint32 = 0
|
||||
for pEvt, epEvt := range p2ep {
|
||||
if (revents & pEvt) != 0 {
|
||||
epollEvts |= epEvt
|
||||
}
|
||||
}
|
||||
|
||||
return epollEvts
|
||||
}
|
||||
|
||||
// Per-process epoll implementation.
|
||||
type epollImpl struct {
|
||||
mu sync.Mutex
|
||||
epfd2ep map[int]*eventPoll
|
||||
nextEpfd int
|
||||
}
|
||||
|
||||
// eventPoll holds a set of file descriptors being watched by the process. A process can have multiple epoll instances.
|
||||
// On Linux, this is an in-kernel data structure accessed through a fd.
|
||||
type eventPoll struct {
|
||||
mu sync.Mutex
|
||||
fds map[int]*EpollEvent
|
||||
}
|
||||
|
||||
// epoll impl for this process.
|
||||
var impl epollImpl = epollImpl{
|
||||
epfd2ep: make(map[int]*eventPoll),
|
||||
nextEpfd: 0,
|
||||
}
|
||||
|
||||
func (e *epollImpl) epollcreate(size int) (epfd int, err error) {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
epfd = e.nextEpfd
|
||||
e.nextEpfd++
|
||||
|
||||
e.epfd2ep[epfd] = &eventPoll{
|
||||
fds: make(map[int]*EpollEvent),
|
||||
}
|
||||
return epfd, nil
|
||||
}
|
||||
|
||||
func (e *epollImpl) epollcreate1(flag int) (fd int, err error) {
|
||||
return e.epollcreate(4)
|
||||
}
|
||||
|
||||
func (e *epollImpl) epollctl(epfd int, op int, fd int, event *EpollEvent) (err error) {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
|
||||
ep, ok := e.epfd2ep[epfd]
|
||||
if !ok {
|
||||
|
||||
return EBADF
|
||||
}
|
||||
|
||||
switch op {
|
||||
case EPOLL_CTL_ADD:
|
||||
// TODO(neeilan): When we make epfds and fds disjoint, detect epoll
|
||||
// loops here (instances watching each other) and return ELOOP.
|
||||
if _, ok := ep.fds[fd]; ok {
|
||||
return EEXIST
|
||||
}
|
||||
ep.fds[fd] = event
|
||||
case EPOLL_CTL_MOD:
|
||||
if _, ok := ep.fds[fd]; !ok {
|
||||
return ENOENT
|
||||
}
|
||||
ep.fds[fd] = event
|
||||
case EPOLL_CTL_DEL:
|
||||
if _, ok := ep.fds[fd]; !ok {
|
||||
return ENOENT
|
||||
}
|
||||
delete(ep.fds, fd)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Must be called while holding ep.mu
|
||||
func (ep *eventPoll) getFds() []int {
|
||||
fds := make([]int, len(ep.fds))
|
||||
for fd := range ep.fds {
|
||||
fds = append(fds, fd)
|
||||
}
|
||||
return fds
|
||||
}
|
||||
|
||||
func (e *epollImpl) epollwait(epfd int, events []EpollEvent, msec int) (n int, err error) {
|
||||
e.mu.Lock() // in [rare] case of concurrent epollcreate + epollwait
|
||||
ep, ok := e.epfd2ep[epfd]
|
||||
|
||||
if !ok {
|
||||
e.mu.Unlock()
|
||||
return 0, EBADF
|
||||
}
|
||||
|
||||
pollfds := make([]PollFd, 4)
|
||||
for fd, epollevt := range ep.fds {
|
||||
pollfds = append(pollfds, PollFd{Fd: int32(fd), Events: epToPollEvt(epollevt.Events)})
|
||||
}
|
||||
e.mu.Unlock()
|
||||
|
||||
n, err = Poll(pollfds, msec)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
i := 0
|
||||
for _, pFd := range pollfds {
|
||||
if pFd.Revents != 0 {
|
||||
events[i] = EpollEvent{Fd: pFd.Fd, Events: pToEpollEvt(pFd.Revents)}
|
||||
i++
|
||||
}
|
||||
|
||||
if i == n {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func EpollCreate(size int) (fd int, err error) {
|
||||
return impl.epollcreate(size)
|
||||
}
|
||||
|
||||
func EpollCreate1(flag int) (fd int, err error) {
|
||||
return impl.epollcreate1(flag)
|
||||
}
|
||||
|
||||
func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
|
||||
return impl.epollctl(epfd, op, fd, event)
|
||||
}
|
||||
|
||||
// Because EpollWait mutates events, the caller is expected to coordinate
|
||||
// concurrent access if calling with the same epfd from multiple goroutines.
|
||||
func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
|
||||
return impl.epollwait(epfd, events, msec)
|
||||
}
|
||||
-163
@@ -1,163 +0,0 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// This file simulates fstatfs on z/OS using fstatvfs and w_getmntent.
|
||||
|
||||
func Fstatfs(fd int, stat *Statfs_t) (err error) {
|
||||
var stat_v Statvfs_t
|
||||
err = Fstatvfs(fd, &stat_v)
|
||||
if err == nil {
|
||||
// populate stat
|
||||
stat.Type = 0
|
||||
stat.Bsize = stat_v.Bsize
|
||||
stat.Blocks = stat_v.Blocks
|
||||
stat.Bfree = stat_v.Bfree
|
||||
stat.Bavail = stat_v.Bavail
|
||||
stat.Files = stat_v.Files
|
||||
stat.Ffree = stat_v.Ffree
|
||||
stat.Fsid = stat_v.Fsid
|
||||
stat.Namelen = stat_v.Namemax
|
||||
stat.Frsize = stat_v.Frsize
|
||||
stat.Flags = stat_v.Flag
|
||||
for passn := 0; passn < 5; passn++ {
|
||||
switch passn {
|
||||
case 0:
|
||||
err = tryGetmntent64(stat)
|
||||
break
|
||||
case 1:
|
||||
err = tryGetmntent128(stat)
|
||||
break
|
||||
case 2:
|
||||
err = tryGetmntent256(stat)
|
||||
break
|
||||
case 3:
|
||||
err = tryGetmntent512(stat)
|
||||
break
|
||||
case 4:
|
||||
err = tryGetmntent1024(stat)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
//proceed to return if: err is nil (found), err is nonnil but not ERANGE (another error occurred)
|
||||
if err == nil || err != nil && err != ERANGE {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func tryGetmntent64(stat *Statfs_t) (err error) {
|
||||
var mnt_ent_buffer struct {
|
||||
header W_Mnth
|
||||
filesys_info [64]W_Mntent
|
||||
}
|
||||
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ERANGE //return ERANGE if no match is found in this batch
|
||||
for i := 0; i < fs_count; i++ {
|
||||
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func tryGetmntent128(stat *Statfs_t) (err error) {
|
||||
var mnt_ent_buffer struct {
|
||||
header W_Mnth
|
||||
filesys_info [128]W_Mntent
|
||||
}
|
||||
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ERANGE //return ERANGE if no match is found in this batch
|
||||
for i := 0; i < fs_count; i++ {
|
||||
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func tryGetmntent256(stat *Statfs_t) (err error) {
|
||||
var mnt_ent_buffer struct {
|
||||
header W_Mnth
|
||||
filesys_info [256]W_Mntent
|
||||
}
|
||||
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ERANGE //return ERANGE if no match is found in this batch
|
||||
for i := 0; i < fs_count; i++ {
|
||||
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func tryGetmntent512(stat *Statfs_t) (err error) {
|
||||
var mnt_ent_buffer struct {
|
||||
header W_Mnth
|
||||
filesys_info [512]W_Mntent
|
||||
}
|
||||
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ERANGE //return ERANGE if no match is found in this batch
|
||||
for i := 0; i < fs_count; i++ {
|
||||
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func tryGetmntent1024(stat *Statfs_t) (err error) {
|
||||
var mnt_ent_buffer struct {
|
||||
header W_Mnth
|
||||
filesys_info [1024]W_Mntent
|
||||
}
|
||||
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ERANGE //return ERANGE if no match is found in this batch
|
||||
for i := 0; i < fs_count; i++ {
|
||||
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
+96
@@ -58,6 +58,102 @@ func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) {
|
||||
return &value, err
|
||||
}
|
||||
|
||||
// IoctlGetEthtoolTsInfo fetches ethtool timestamping and PHC
|
||||
// association for the network device specified by ifname.
|
||||
func IoctlGetEthtoolTsInfo(fd int, ifname string) (*EthtoolTsInfo, error) {
|
||||
ifr, err := NewIfreq(ifname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value := EthtoolTsInfo{Cmd: ETHTOOL_GET_TS_INFO}
|
||||
ifrd := ifr.withData(unsafe.Pointer(&value))
|
||||
|
||||
err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd)
|
||||
return &value, err
|
||||
}
|
||||
|
||||
// IoctlGetHwTstamp retrieves the hardware timestamping configuration
|
||||
// for the network device specified by ifname.
|
||||
func IoctlGetHwTstamp(fd int, ifname string) (*HwTstampConfig, error) {
|
||||
ifr, err := NewIfreq(ifname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value := HwTstampConfig{}
|
||||
ifrd := ifr.withData(unsafe.Pointer(&value))
|
||||
|
||||
err = ioctlIfreqData(fd, SIOCGHWTSTAMP, &ifrd)
|
||||
return &value, err
|
||||
}
|
||||
|
||||
// IoctlSetHwTstamp updates the hardware timestamping configuration for
|
||||
// the network device specified by ifname.
|
||||
func IoctlSetHwTstamp(fd int, ifname string, cfg *HwTstampConfig) error {
|
||||
ifr, err := NewIfreq(ifname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ifrd := ifr.withData(unsafe.Pointer(cfg))
|
||||
return ioctlIfreqData(fd, SIOCSHWTSTAMP, &ifrd)
|
||||
}
|
||||
|
||||
// FdToClockID derives the clock ID from the file descriptor number
|
||||
// - see clock_gettime(3), FD_TO_CLOCKID macros. The resulting ID is
|
||||
// suitable for system calls like ClockGettime.
|
||||
func FdToClockID(fd int) int32 { return int32((int(^fd) << 3) | 3) }
|
||||
|
||||
// IoctlPtpClockGetcaps returns the description of a given PTP device.
|
||||
func IoctlPtpClockGetcaps(fd int) (*PtpClockCaps, error) {
|
||||
var value PtpClockCaps
|
||||
err := ioctlPtr(fd, PTP_CLOCK_GETCAPS2, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
// IoctlPtpSysOffsetPrecise returns a description of the clock
|
||||
// offset compared to the system clock.
|
||||
func IoctlPtpSysOffsetPrecise(fd int) (*PtpSysOffsetPrecise, error) {
|
||||
var value PtpSysOffsetPrecise
|
||||
err := ioctlPtr(fd, PTP_SYS_OFFSET_PRECISE2, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
// IoctlPtpSysOffsetExtended returns an extended description of the
|
||||
// clock offset compared to the system clock. The samples parameter
|
||||
// specifies the desired number of measurements.
|
||||
func IoctlPtpSysOffsetExtended(fd int, samples uint) (*PtpSysOffsetExtended, error) {
|
||||
value := PtpSysOffsetExtended{Samples: uint32(samples)}
|
||||
err := ioctlPtr(fd, PTP_SYS_OFFSET_EXTENDED2, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
// IoctlPtpPinGetfunc returns the configuration of the specified
|
||||
// I/O pin on given PTP device.
|
||||
func IoctlPtpPinGetfunc(fd int, index uint) (*PtpPinDesc, error) {
|
||||
value := PtpPinDesc{Index: uint32(index)}
|
||||
err := ioctlPtr(fd, PTP_PIN_GETFUNC2, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
// IoctlPtpPinSetfunc updates configuration of the specified PTP
|
||||
// I/O pin.
|
||||
func IoctlPtpPinSetfunc(fd int, pd *PtpPinDesc) error {
|
||||
return ioctlPtr(fd, PTP_PIN_SETFUNC2, unsafe.Pointer(pd))
|
||||
}
|
||||
|
||||
// IoctlPtpPeroutRequest configures the periodic output mode of the
|
||||
// PTP I/O pins.
|
||||
func IoctlPtpPeroutRequest(fd int, r *PtpPeroutRequest) error {
|
||||
return ioctlPtr(fd, PTP_PEROUT_REQUEST2, unsafe.Pointer(r))
|
||||
}
|
||||
|
||||
// IoctlPtpExttsRequest configures the external timestamping mode
|
||||
// of the PTP I/O pins.
|
||||
func IoctlPtpExttsRequest(fd int, r *PtpExttsRequest) error {
|
||||
return ioctlPtr(fd, PTP_EXTTS_REQUEST2, unsafe.Pointer(r))
|
||||
}
|
||||
|
||||
// IoctlGetWatchdogInfo fetches information about a watchdog device from the
|
||||
// Linux watchdog API. For more information, see:
|
||||
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
|
||||
|
||||
+18
-2
@@ -58,6 +58,7 @@ includes_Darwin='
|
||||
#define _DARWIN_USE_64_BIT_INODE
|
||||
#define __APPLE_USE_RFC_3542
|
||||
#include <stdint.h>
|
||||
#include <sys/stdio.h>
|
||||
#include <sys/attr.h>
|
||||
#include <sys/clonefile.h>
|
||||
#include <sys/kern_control.h>
|
||||
@@ -157,6 +158,16 @@ includes_Linux='
|
||||
#endif
|
||||
#define _GNU_SOURCE
|
||||
|
||||
// See the description in unix/linux/types.go
|
||||
#if defined(__ARM_EABI__) || \
|
||||
(defined(__mips__) && (_MIPS_SIM == _ABIO32)) || \
|
||||
(defined(__powerpc__) && (!defined(__powerpc64__)))
|
||||
# ifdef _TIME_BITS
|
||||
# undef _TIME_BITS
|
||||
# endif
|
||||
# define _TIME_BITS 32
|
||||
#endif
|
||||
|
||||
// <sys/ioctl.h> is broken on powerpc64, as it fails to include definitions of
|
||||
// these structures. We just include them copied from <bits/termios.h>.
|
||||
#if defined(__powerpc__)
|
||||
@@ -255,6 +266,7 @@ struct ltchars {
|
||||
#include <linux/nsfs.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/pps.h>
|
||||
#include <linux/ptp_clock.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/reboot.h>
|
||||
@@ -263,6 +275,7 @@ struct ltchars {
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seccomp.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/sock_diag.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/taskstats.h>
|
||||
#include <linux/tipc.h>
|
||||
@@ -525,6 +538,7 @@ ccflags="$@"
|
||||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
|
||||
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
|
||||
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
|
||||
$2 ~ /^PTP_/ ||
|
||||
$2 ~ /^RAW_PAYLOAD_/ ||
|
||||
$2 ~ /^[US]F_/ ||
|
||||
$2 ~ /^TP_STATUS_/ ||
|
||||
@@ -549,6 +563,8 @@ ccflags="$@"
|
||||
$2 !~ "NLA_TYPE_MASK" &&
|
||||
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
|
||||
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
|
||||
$2 ~ /^SOCK_|SK_DIAG_|SKNLGRP_$/ ||
|
||||
$2 ~ /^(CONNECT|SAE)_/ ||
|
||||
$2 ~ /^FIORDCHK$/ ||
|
||||
$2 ~ /^SIOC/ ||
|
||||
$2 ~ /^TIOC/ ||
|
||||
@@ -652,7 +668,7 @@ errors=$(
|
||||
signals=$(
|
||||
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
|
||||
grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
|
||||
grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
|
||||
sort
|
||||
)
|
||||
|
||||
@@ -662,7 +678,7 @@ echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
|
||||
sort >_error.grep
|
||||
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
||||
grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
|
||||
grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
|
||||
sort >_signal.grep
|
||||
|
||||
echo '// mkerrors.sh' "$@"
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris
|
||||
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris || zos
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
+5
@@ -50,3 +50,8 @@ func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data [
|
||||
func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
|
||||
return mapper.Mremap(oldData, newLength, flags)
|
||||
}
|
||||
|
||||
func MremapPtr(oldAddr unsafe.Pointer, oldSize uintptr, newAddr unsafe.Pointer, newSize uintptr, flags int) (ret unsafe.Pointer, err error) {
|
||||
xaddr, err := mapper.mremap(uintptr(oldAddr), oldSize, newSize, flags, uintptr(newAddr))
|
||||
return unsafe.Pointer(xaddr), err
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
|
||||
// For Unix, get the pagesize from the runtime.
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin
|
||||
//go:build darwin || zos
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// Copyright 2024 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.
|
||||
|
||||
// Socket control messages
|
||||
|
||||
package unix
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// UnixCredentials encodes credentials into a socket control message
|
||||
// for sending to another process. This can be used for
|
||||
// authentication.
|
||||
func UnixCredentials(ucred *Ucred) []byte {
|
||||
b := make([]byte, CmsgSpace(SizeofUcred))
|
||||
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||
h.Level = SOL_SOCKET
|
||||
h.Type = SCM_CREDENTIALS
|
||||
h.SetLen(CmsgLen(SizeofUcred))
|
||||
*(*Ucred)(h.data(0)) = *ucred
|
||||
return b
|
||||
}
|
||||
|
||||
// ParseUnixCredentials decodes a socket control message that contains
|
||||
// credentials in a Ucred structure. To receive such a message, the
|
||||
// SO_PASSCRED option must be enabled on the socket.
|
||||
func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
|
||||
if m.Header.Level != SOL_SOCKET {
|
||||
return nil, EINVAL
|
||||
}
|
||||
if m.Header.Type != SCM_CREDENTIALS {
|
||||
return nil, EINVAL
|
||||
}
|
||||
ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
|
||||
return &ucred, nil
|
||||
}
|
||||
|
||||
// PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO.
|
||||
func PktInfo4(info *Inet4Pktinfo) []byte {
|
||||
b := make([]byte, CmsgSpace(SizeofInet4Pktinfo))
|
||||
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||
h.Level = SOL_IP
|
||||
h.Type = IP_PKTINFO
|
||||
h.SetLen(CmsgLen(SizeofInet4Pktinfo))
|
||||
*(*Inet4Pktinfo)(h.data(0)) = *info
|
||||
return b
|
||||
}
|
||||
|
||||
// PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO.
|
||||
func PktInfo6(info *Inet6Pktinfo) []byte {
|
||||
b := make([]byte, CmsgSpace(SizeofInet6Pktinfo))
|
||||
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||
h.Level = SOL_IPV6
|
||||
h.Type = IPV6_PKTINFO
|
||||
h.SetLen(CmsgLen(SizeofInet6Pktinfo))
|
||||
*(*Inet6Pktinfo)(h.data(0)) = *info
|
||||
return b
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
// Copyright 2024 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 zos && s390x && gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// provide the address of function variable to be fixed up.
|
||||
|
||||
TEXT ·getPipe2Addr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Pipe2(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_FlockAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Flock(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_GetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Getxattr(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_NanosleepAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Nanosleep(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_SetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Setxattr(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_Wait4Addr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Wait4(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_MountAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Mount(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_UnmountAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Unmount(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_UtimesNanoAtAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·UtimesNanoAt(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_UtimesNanoAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·UtimesNano(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_MkfifoatAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Mkfifoat(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_ChtagAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Chtag(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT ·get_ReadlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVD $·Readlinkat(SB), R8
|
||||
MOVD R8, ret+0(FP)
|
||||
RET
|
||||
|
||||
+1
-1
@@ -360,7 +360,7 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int,
|
||||
var status _C_int
|
||||
var r Pid_t
|
||||
err = ERESTART
|
||||
// AIX wait4 may return with ERESTART errno, while the processus is still
|
||||
// AIX wait4 may return with ERESTART errno, while the process is still
|
||||
// active.
|
||||
for err == ERESTART {
|
||||
r, err = wait4(Pid_t(pid), &status, options, rusage)
|
||||
|
||||
+208
@@ -402,6 +402,18 @@ func IoctlSetIfreqMTU(fd int, ifreq *IfreqMTU) error {
|
||||
return ioctlPtr(fd, SIOCSIFMTU, unsafe.Pointer(ifreq))
|
||||
}
|
||||
|
||||
//sys renamexNp(from string, to string, flag uint32) (err error)
|
||||
|
||||
func RenamexNp(from string, to string, flag uint32) (err error) {
|
||||
return renamexNp(from, to, flag)
|
||||
}
|
||||
|
||||
//sys renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error)
|
||||
|
||||
func RenameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) {
|
||||
return renameatxNp(fromfd, from, tofd, to, flag)
|
||||
}
|
||||
|
||||
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL
|
||||
|
||||
func Uname(uname *Utsname) error {
|
||||
@@ -542,6 +554,198 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
|
||||
}
|
||||
}
|
||||
|
||||
//sys pthread_chdir_np(path string) (err error)
|
||||
|
||||
func PthreadChdir(path string) (err error) {
|
||||
return pthread_chdir_np(path)
|
||||
}
|
||||
|
||||
//sys pthread_fchdir_np(fd int) (err error)
|
||||
|
||||
func PthreadFchdir(fd int) (err error) {
|
||||
return pthread_fchdir_np(fd)
|
||||
}
|
||||
|
||||
// Connectx calls connectx(2) to initiate a connection on a socket.
|
||||
//
|
||||
// srcIf, srcAddr, and dstAddr are filled into a [SaEndpoints] struct and passed as the endpoints argument.
|
||||
//
|
||||
// - srcIf is the optional source interface index. 0 means unspecified.
|
||||
// - srcAddr is the optional source address. nil means unspecified.
|
||||
// - dstAddr is the destination address.
|
||||
//
|
||||
// On success, Connectx returns the number of bytes enqueued for transmission.
|
||||
func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocID, flags uint32, iov []Iovec, connid *SaeConnID) (n uintptr, err error) {
|
||||
endpoints := SaEndpoints{
|
||||
Srcif: srcIf,
|
||||
}
|
||||
|
||||
if srcAddr != nil {
|
||||
addrp, addrlen, err := srcAddr.sockaddr()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
endpoints.Srcaddr = (*RawSockaddr)(addrp)
|
||||
endpoints.Srcaddrlen = uint32(addrlen)
|
||||
}
|
||||
|
||||
if dstAddr != nil {
|
||||
addrp, addrlen, err := dstAddr.sockaddr()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
endpoints.Dstaddr = (*RawSockaddr)(addrp)
|
||||
endpoints.Dstaddrlen = uint32(addrlen)
|
||||
}
|
||||
|
||||
err = connectx(fd, &endpoints, associd, flags, iov, &n, connid)
|
||||
return
|
||||
}
|
||||
|
||||
// sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error)
|
||||
const minIovec = 8
|
||||
|
||||
func Readv(fd int, iovs [][]byte) (n int, err error) {
|
||||
if !darwinKernelVersionMin(11, 0, 0) {
|
||||
return 0, ENOSYS
|
||||
}
|
||||
|
||||
iovecs := make([]Iovec, 0, minIovec)
|
||||
iovecs = appendBytes(iovecs, iovs)
|
||||
n, err = readv(fd, iovecs)
|
||||
readvRacedetect(iovecs, n, err)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) {
|
||||
if !darwinKernelVersionMin(11, 0, 0) {
|
||||
return 0, ENOSYS
|
||||
}
|
||||
iovecs := make([]Iovec, 0, minIovec)
|
||||
iovecs = appendBytes(iovecs, iovs)
|
||||
n, err = preadv(fd, iovecs, offset)
|
||||
readvRacedetect(iovecs, n, err)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func Writev(fd int, iovs [][]byte) (n int, err error) {
|
||||
if !darwinKernelVersionMin(11, 0, 0) {
|
||||
return 0, ENOSYS
|
||||
}
|
||||
|
||||
iovecs := make([]Iovec, 0, minIovec)
|
||||
iovecs = appendBytes(iovecs, iovs)
|
||||
if raceenabled {
|
||||
raceReleaseMerge(unsafe.Pointer(&ioSync))
|
||||
}
|
||||
n, err = writev(fd, iovecs)
|
||||
writevRacedetect(iovecs, n)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) {
|
||||
if !darwinKernelVersionMin(11, 0, 0) {
|
||||
return 0, ENOSYS
|
||||
}
|
||||
|
||||
iovecs := make([]Iovec, 0, minIovec)
|
||||
iovecs = appendBytes(iovecs, iovs)
|
||||
if raceenabled {
|
||||
raceReleaseMerge(unsafe.Pointer(&ioSync))
|
||||
}
|
||||
n, err = pwritev(fd, iovecs, offset)
|
||||
writevRacedetect(iovecs, n)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func appendBytes(vecs []Iovec, bs [][]byte) []Iovec {
|
||||
for _, b := range bs {
|
||||
var v Iovec
|
||||
v.SetLen(len(b))
|
||||
if len(b) > 0 {
|
||||
v.Base = &b[0]
|
||||
} else {
|
||||
v.Base = (*byte)(unsafe.Pointer(&_zero))
|
||||
}
|
||||
vecs = append(vecs, v)
|
||||
}
|
||||
return vecs
|
||||
}
|
||||
|
||||
func writevRacedetect(iovecs []Iovec, n int) {
|
||||
if !raceenabled {
|
||||
return
|
||||
}
|
||||
for i := 0; n > 0 && i < len(iovecs); i++ {
|
||||
m := int(iovecs[i].Len)
|
||||
if m > n {
|
||||
m = n
|
||||
}
|
||||
n -= m
|
||||
if m > 0 {
|
||||
raceReadRange(unsafe.Pointer(iovecs[i].Base), m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readvRacedetect(iovecs []Iovec, n int, err error) {
|
||||
if !raceenabled {
|
||||
return
|
||||
}
|
||||
for i := 0; n > 0 && i < len(iovecs); i++ {
|
||||
m := int(iovecs[i].Len)
|
||||
if m > n {
|
||||
m = n
|
||||
}
|
||||
n -= m
|
||||
if m > 0 {
|
||||
raceWriteRange(unsafe.Pointer(iovecs[i].Base), m)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
raceAcquire(unsafe.Pointer(&ioSync))
|
||||
}
|
||||
}
|
||||
|
||||
func darwinMajorMinPatch() (maj, min, patch int, err error) {
|
||||
var un Utsname
|
||||
err = Uname(&un)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var mmp [3]int
|
||||
c := 0
|
||||
Loop:
|
||||
for _, b := range un.Release[:] {
|
||||
switch {
|
||||
case b >= '0' && b <= '9':
|
||||
mmp[c] = 10*mmp[c] + int(b-'0')
|
||||
case b == '.':
|
||||
c++
|
||||
if c > 2 {
|
||||
return 0, 0, 0, ENOTSUP
|
||||
}
|
||||
case b == 0:
|
||||
break Loop
|
||||
default:
|
||||
return 0, 0, 0, ENOTSUP
|
||||
}
|
||||
}
|
||||
if c != 2 {
|
||||
return 0, 0, 0, ENOTSUP
|
||||
}
|
||||
return mmp[0], mmp[1], mmp[2], nil
|
||||
}
|
||||
|
||||
func darwinKernelVersionMin(maj, min, patch int) bool {
|
||||
actualMaj, actualMin, actualPatch, err := darwinMajorMinPatch()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return actualMaj > maj || actualMaj == maj && (actualMin > min || actualMin == min && actualPatch >= patch)
|
||||
}
|
||||
|
||||
//sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error)
|
||||
|
||||
//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error)
|
||||
@@ -644,3 +848,7 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
|
||||
//sys write(fd int, p []byte) (n int, err error)
|
||||
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
|
||||
//sys munmap(addr uintptr, length uintptr) (err error)
|
||||
//sys readv(fd int, iovecs []Iovec) (n int, err error)
|
||||
//sys preadv(fd int, iovecs []Iovec, offset int64) (n int, err error)
|
||||
//sys writev(fd int, iovecs []Iovec) (n int, err error)
|
||||
//sys pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error)
|
||||
+12
@@ -246,6 +246,18 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
return sendfile(outfd, infd, offset, count)
|
||||
}
|
||||
|
||||
func Dup3(oldfd, newfd, flags int) error {
|
||||
if oldfd == newfd || flags&^O_CLOEXEC != 0 {
|
||||
return EINVAL
|
||||
}
|
||||
how := F_DUP2FD
|
||||
if flags&O_CLOEXEC != 0 {
|
||||
how = F_DUP2FD_CLOEXEC
|
||||
}
|
||||
_, err := fcntl(oldfd, how, newfd)
|
||||
return err
|
||||
}
|
||||
|
||||
/*
|
||||
* Exposed directly
|
||||
*/
|
||||
|
||||
+1
@@ -11,6 +11,7 @@ package unix
|
||||
int ioctl(int, unsigned long int, uintptr_t);
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func ioctl(fd int, req uint, arg uintptr) (err error) {
|
||||
r0, er := C.ioctl(C.int(fd), C.ulong(req), C.uintptr_t(arg))
|
||||
|
||||
+80
-27
@@ -13,6 +13,7 @@ package unix
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"slices"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
@@ -417,7 +418,7 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
return nil, 0, EINVAL
|
||||
}
|
||||
sa.raw.Family = AF_UNIX
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
sa.raw.Path[i] = int8(name[i])
|
||||
}
|
||||
// length is family (uint16), name, NUL.
|
||||
@@ -507,7 +508,7 @@ func (sa *SockaddrL2) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
psm := (*[2]byte)(unsafe.Pointer(&sa.raw.Psm))
|
||||
psm[0] = byte(sa.PSM)
|
||||
psm[1] = byte(sa.PSM >> 8)
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
for i := range len(sa.Addr) {
|
||||
sa.raw.Bdaddr[i] = sa.Addr[len(sa.Addr)-1-i]
|
||||
}
|
||||
cid := (*[2]byte)(unsafe.Pointer(&sa.raw.Cid))
|
||||
@@ -589,11 +590,11 @@ func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
sa.raw.Family = AF_CAN
|
||||
sa.raw.Ifindex = int32(sa.Ifindex)
|
||||
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := range 4 {
|
||||
sa.raw.Addr[i] = rx[i]
|
||||
}
|
||||
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := range 4 {
|
||||
sa.raw.Addr[i+4] = tx[i]
|
||||
}
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
|
||||
@@ -618,11 +619,11 @@ func (sa *SockaddrCANJ1939) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
sa.raw.Family = AF_CAN
|
||||
sa.raw.Ifindex = int32(sa.Ifindex)
|
||||
n := (*[8]byte)(unsafe.Pointer(&sa.Name))
|
||||
for i := 0; i < 8; i++ {
|
||||
for i := range 8 {
|
||||
sa.raw.Addr[i] = n[i]
|
||||
}
|
||||
p := (*[4]byte)(unsafe.Pointer(&sa.PGN))
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := range 4 {
|
||||
sa.raw.Addr[i+8] = p[i]
|
||||
}
|
||||
sa.raw.Addr[12] = sa.Addr
|
||||
@@ -911,7 +912,7 @@ func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
// These are EBCDIC encoded by the kernel, but we still need to pad them
|
||||
// with blanks. Initializing with blanks allows the caller to feed in either
|
||||
// a padded or an unpadded string.
|
||||
for i := 0; i < 8; i++ {
|
||||
for i := range 8 {
|
||||
sa.raw.Nodeid[i] = ' '
|
||||
sa.raw.User_id[i] = ' '
|
||||
sa.raw.Name[i] = ' '
|
||||
@@ -1148,7 +1149,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
var user [8]byte
|
||||
var name [8]byte
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
for i := range 8 {
|
||||
user[i] = byte(pp.User_id[i])
|
||||
name[i] = byte(pp.Name[i])
|
||||
}
|
||||
@@ -1173,11 +1174,11 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
Ifindex: int(pp.Ifindex),
|
||||
}
|
||||
name := (*[8]byte)(unsafe.Pointer(&sa.Name))
|
||||
for i := 0; i < 8; i++ {
|
||||
for i := range 8 {
|
||||
name[i] = pp.Addr[i]
|
||||
}
|
||||
pgn := (*[4]byte)(unsafe.Pointer(&sa.PGN))
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := range 4 {
|
||||
pgn[i] = pp.Addr[i+8]
|
||||
}
|
||||
addr := (*[1]byte)(unsafe.Pointer(&sa.Addr))
|
||||
@@ -1188,11 +1189,11 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
Ifindex: int(pp.Ifindex),
|
||||
}
|
||||
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := range 4 {
|
||||
rx[i] = pp.Addr[i]
|
||||
}
|
||||
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := range 4 {
|
||||
tx[i] = pp.Addr[i+4]
|
||||
}
|
||||
return sa, nil
|
||||
@@ -1295,6 +1296,48 @@ func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
|
||||
return &value, err
|
||||
}
|
||||
|
||||
// GetsockoptTCPCCVegasInfo returns algorithm specific congestion control information for a socket using the "vegas"
|
||||
// algorithm.
|
||||
//
|
||||
// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option:
|
||||
//
|
||||
// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION)
|
||||
func GetsockoptTCPCCVegasInfo(fd, level, opt int) (*TCPVegasInfo, error) {
|
||||
var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment
|
||||
vallen := _Socklen(SizeofTCPCCInfo)
|
||||
err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
|
||||
out := (*TCPVegasInfo)(unsafe.Pointer(&value[0]))
|
||||
return out, err
|
||||
}
|
||||
|
||||
// GetsockoptTCPCCDCTCPInfo returns algorithm specific congestion control information for a socket using the "dctp"
|
||||
// algorithm.
|
||||
//
|
||||
// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option:
|
||||
//
|
||||
// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION)
|
||||
func GetsockoptTCPCCDCTCPInfo(fd, level, opt int) (*TCPDCTCPInfo, error) {
|
||||
var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment
|
||||
vallen := _Socklen(SizeofTCPCCInfo)
|
||||
err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
|
||||
out := (*TCPDCTCPInfo)(unsafe.Pointer(&value[0]))
|
||||
return out, err
|
||||
}
|
||||
|
||||
// GetsockoptTCPCCBBRInfo returns algorithm specific congestion control information for a socket using the "bbr"
|
||||
// algorithm.
|
||||
//
|
||||
// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option:
|
||||
//
|
||||
// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION)
|
||||
func GetsockoptTCPCCBBRInfo(fd, level, opt int) (*TCPBBRInfo, error) {
|
||||
var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment
|
||||
vallen := _Socklen(SizeofTCPCCInfo)
|
||||
err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
|
||||
out := (*TCPBBRInfo)(unsafe.Pointer(&value[0]))
|
||||
return out, err
|
||||
}
|
||||
|
||||
// GetsockoptString returns the string value of the socket option opt for the
|
||||
// socket associated with fd at the given socket level.
|
||||
func GetsockoptString(fd, level, opt int) (string, error) {
|
||||
@@ -1818,6 +1861,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
//sys ClockAdjtime(clockid int32, buf *Timex) (state int, err error)
|
||||
//sys ClockGetres(clockid int32, res *Timespec) (err error)
|
||||
//sys ClockGettime(clockid int32, time *Timespec) (err error)
|
||||
//sys ClockSettime(clockid int32, time *Timespec) (err error)
|
||||
//sys ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error)
|
||||
//sys Close(fd int) (err error)
|
||||
//sys CloseRange(first uint, last uint, flags uint) (err error)
|
||||
@@ -1959,7 +2003,26 @@ func Getpgrp() (pid int) {
|
||||
//sysnb Getpid() (pid int)
|
||||
//sysnb Getppid() (ppid int)
|
||||
//sys Getpriority(which int, who int) (prio int, err error)
|
||||
//sys Getrandom(buf []byte, flags int) (n int, err error)
|
||||
|
||||
func Getrandom(buf []byte, flags int) (n int, err error) {
|
||||
vdsoRet, supported := vgetrandom(buf, uint32(flags))
|
||||
if supported {
|
||||
if vdsoRet < 0 {
|
||||
return 0, errnoErr(syscall.Errno(-vdsoRet))
|
||||
}
|
||||
return vdsoRet, nil
|
||||
}
|
||||
var p *byte
|
||||
if len(buf) > 0 {
|
||||
p = &buf[0]
|
||||
}
|
||||
r, _, e := Syscall(SYS_GETRANDOM, uintptr(unsafe.Pointer(p)), uintptr(len(buf)), uintptr(flags))
|
||||
if e != 0 {
|
||||
return 0, errnoErr(e)
|
||||
}
|
||||
return int(r), nil
|
||||
}
|
||||
|
||||
//sysnb Getrusage(who int, rusage *Rusage) (err error)
|
||||
//sysnb Getsid(pid int) (sid int, err error)
|
||||
//sysnb Gettid() (tid int)
|
||||
@@ -2154,10 +2217,7 @@ func readvRacedetect(iovecs []Iovec, n int, err error) {
|
||||
return
|
||||
}
|
||||
for i := 0; n > 0 && i < len(iovecs); i++ {
|
||||
m := int(iovecs[i].Len)
|
||||
if m > n {
|
||||
m = n
|
||||
}
|
||||
m := min(int(iovecs[i].Len), n)
|
||||
n -= m
|
||||
if m > 0 {
|
||||
raceWriteRange(unsafe.Pointer(iovecs[i].Base), m)
|
||||
@@ -2208,10 +2268,7 @@ func writevRacedetect(iovecs []Iovec, n int) {
|
||||
return
|
||||
}
|
||||
for i := 0; n > 0 && i < len(iovecs); i++ {
|
||||
m := int(iovecs[i].Len)
|
||||
if m > n {
|
||||
m = n
|
||||
}
|
||||
m := min(int(iovecs[i].Len), n)
|
||||
n -= m
|
||||
if m > 0 {
|
||||
raceReadRange(unsafe.Pointer(iovecs[i].Base), m)
|
||||
@@ -2258,12 +2315,7 @@ func isGroupMember(gid int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, g := range groups {
|
||||
if g == gid {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(groups, gid)
|
||||
}
|
||||
|
||||
func isCapDacOverrideSet() bool {
|
||||
@@ -2592,3 +2644,4 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) {
|
||||
}
|
||||
|
||||
//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error)
|
||||
//sys Mseal(b []byte, flags uint) (err error)
|
||||
+2
@@ -182,3 +182,5 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
|
||||
}
|
||||
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
|
||||
}
|
||||
|
||||
const SYS_FSTATAT = SYS_NEWFSTATAT
|
||||
+2
@@ -214,3 +214,5 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
|
||||
}
|
||||
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
|
||||
}
|
||||
|
||||
const SYS_FSTATAT = SYS_NEWFSTATAT
|
||||
+2
@@ -187,3 +187,5 @@ func RISCVHWProbe(pairs []RISCVHWProbePairs, set *CPUSet, flags uint) (err error
|
||||
}
|
||||
return riscvHWProbe(pairs, setSize, set, flags)
|
||||
}
|
||||
|
||||
const SYS_FSTATAT = SYS_NEWFSTATAT
|
||||
+1
@@ -293,6 +293,7 @@ func Uname(uname *Utsname) error {
|
||||
//sys Mkfifoat(dirfd int, path string, mode uint32) (err error)
|
||||
//sys Mknod(path string, mode uint32, dev int) (err error)
|
||||
//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
|
||||
//sys Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error)
|
||||
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
|
||||
//sys Open(path string, mode int, perm uint32) (fd int, err error)
|
||||
//sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error)
|
||||
|
||||
+87
@@ -1102,3 +1102,90 @@ func (s *Strioctl) SetInt(i int) {
|
||||
func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) {
|
||||
return ioctlPtrRet(fd, req, unsafe.Pointer(s))
|
||||
}
|
||||
|
||||
// Ucred Helpers
|
||||
// See ucred(3c) and getpeerucred(3c)
|
||||
|
||||
//sys getpeerucred(fd uintptr, ucred *uintptr) (err error)
|
||||
//sys ucredFree(ucred uintptr) = ucred_free
|
||||
//sys ucredGet(pid int) (ucred uintptr, err error) = ucred_get
|
||||
//sys ucredGeteuid(ucred uintptr) (uid int) = ucred_geteuid
|
||||
//sys ucredGetegid(ucred uintptr) (gid int) = ucred_getegid
|
||||
//sys ucredGetruid(ucred uintptr) (uid int) = ucred_getruid
|
||||
//sys ucredGetrgid(ucred uintptr) (gid int) = ucred_getrgid
|
||||
//sys ucredGetsuid(ucred uintptr) (uid int) = ucred_getsuid
|
||||
//sys ucredGetsgid(ucred uintptr) (gid int) = ucred_getsgid
|
||||
//sys ucredGetpid(ucred uintptr) (pid int) = ucred_getpid
|
||||
|
||||
// Ucred is an opaque struct that holds user credentials.
|
||||
type Ucred struct {
|
||||
ucred uintptr
|
||||
}
|
||||
|
||||
// We need to ensure that ucredFree is called on the underlying ucred
|
||||
// when the Ucred is garbage collected.
|
||||
func ucredFinalizer(u *Ucred) {
|
||||
ucredFree(u.ucred)
|
||||
}
|
||||
|
||||
func GetPeerUcred(fd uintptr) (*Ucred, error) {
|
||||
var ucred uintptr
|
||||
err := getpeerucred(fd, &ucred)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := &Ucred{
|
||||
ucred: ucred,
|
||||
}
|
||||
// set the finalizer on the result so that the ucred will be freed
|
||||
runtime.SetFinalizer(result, ucredFinalizer)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func UcredGet(pid int) (*Ucred, error) {
|
||||
ucred, err := ucredGet(pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := &Ucred{
|
||||
ucred: ucred,
|
||||
}
|
||||
// set the finalizer on the result so that the ucred will be freed
|
||||
runtime.SetFinalizer(result, ucredFinalizer)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (u *Ucred) Geteuid() int {
|
||||
defer runtime.KeepAlive(u)
|
||||
return ucredGeteuid(u.ucred)
|
||||
}
|
||||
|
||||
func (u *Ucred) Getruid() int {
|
||||
defer runtime.KeepAlive(u)
|
||||
return ucredGetruid(u.ucred)
|
||||
}
|
||||
|
||||
func (u *Ucred) Getsuid() int {
|
||||
defer runtime.KeepAlive(u)
|
||||
return ucredGetsuid(u.ucred)
|
||||
}
|
||||
|
||||
func (u *Ucred) Getegid() int {
|
||||
defer runtime.KeepAlive(u)
|
||||
return ucredGetegid(u.ucred)
|
||||
}
|
||||
|
||||
func (u *Ucred) Getrgid() int {
|
||||
defer runtime.KeepAlive(u)
|
||||
return ucredGetrgid(u.ucred)
|
||||
}
|
||||
|
||||
func (u *Ucred) Getsgid() int {
|
||||
defer runtime.KeepAlive(u)
|
||||
return ucredGetsgid(u.ucred)
|
||||
}
|
||||
|
||||
func (u *Ucred) Getpid() int {
|
||||
defer runtime.KeepAlive(u)
|
||||
return ucredGetpid(u.ucred)
|
||||
}
|
||||
+9
@@ -154,6 +154,15 @@ func Munmap(b []byte) (err error) {
|
||||
return mapper.Munmap(b)
|
||||
}
|
||||
|
||||
func MmapPtr(fd int, offset int64, addr unsafe.Pointer, length uintptr, prot int, flags int) (ret unsafe.Pointer, err error) {
|
||||
xaddr, err := mapper.mmap(uintptr(addr), length, prot, flags, fd, offset)
|
||||
return unsafe.Pointer(xaddr), err
|
||||
}
|
||||
|
||||
func MunmapPtr(addr unsafe.Pointer, length uintptr) (err error) {
|
||||
return mapper.munmap(uintptr(addr), length)
|
||||
}
|
||||
|
||||
func Read(fd int, p []byte) (n int, err error) {
|
||||
n, err = read(fd, p)
|
||||
if raceenabled {
|
||||
|
||||
+1416
-181
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (darwin && !ios) || linux
|
||||
//go:build (darwin && !ios) || linux || zos
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && !ios
|
||||
//go:build (darwin && !ios) || zos
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 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 linux && go1.24
|
||||
|
||||
package unix
|
||||
|
||||
import _ "unsafe"
|
||||
|
||||
//go:linkname vgetrandom runtime.vgetrandom
|
||||
//go:noescape
|
||||
func vgetrandom(p []byte, flags uint32) (ret int, supported bool)
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// Copyright 2024 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 !linux || !go1.24
|
||||
|
||||
package unix
|
||||
|
||||
func vgetrandom(p []byte, flags uint32) (ret int, supported bool) {
|
||||
return -1, false
|
||||
}
|
||||
+12
@@ -237,6 +237,9 @@ const (
|
||||
CLOCK_UPTIME_RAW_APPROX = 0x9
|
||||
CLONE_NOFOLLOW = 0x1
|
||||
CLONE_NOOWNERCOPY = 0x2
|
||||
CONNECT_DATA_AUTHENTICATED = 0x4
|
||||
CONNECT_DATA_IDEMPOTENT = 0x2
|
||||
CONNECT_RESUME_ON_READ_WRITE = 0x1
|
||||
CR0 = 0x0
|
||||
CR1 = 0x1000
|
||||
CR2 = 0x2000
|
||||
@@ -1169,6 +1172,11 @@ const (
|
||||
PT_WRITE_D = 0x5
|
||||
PT_WRITE_I = 0x4
|
||||
PT_WRITE_U = 0x6
|
||||
RENAME_EXCL = 0x4
|
||||
RENAME_NOFOLLOW_ANY = 0x10
|
||||
RENAME_RESERVED1 = 0x8
|
||||
RENAME_SECLUDE = 0x1
|
||||
RENAME_SWAP = 0x2
|
||||
RLIMIT_AS = 0x5
|
||||
RLIMIT_CORE = 0x4
|
||||
RLIMIT_CPU = 0x0
|
||||
@@ -1260,6 +1268,10 @@ const (
|
||||
RTV_SSTHRESH = 0x20
|
||||
RUSAGE_CHILDREN = -0x1
|
||||
RUSAGE_SELF = 0x0
|
||||
SAE_ASSOCID_ALL = 0xffffffff
|
||||
SAE_ASSOCID_ANY = 0x0
|
||||
SAE_CONNID_ALL = 0xffffffff
|
||||
SAE_CONNID_ANY = 0x0
|
||||
SCM_CREDS = 0x3
|
||||
SCM_RIGHTS = 0x1
|
||||
SCM_TIMESTAMP = 0x2
|
||||
|
||||
+12
@@ -237,6 +237,9 @@ const (
|
||||
CLOCK_UPTIME_RAW_APPROX = 0x9
|
||||
CLONE_NOFOLLOW = 0x1
|
||||
CLONE_NOOWNERCOPY = 0x2
|
||||
CONNECT_DATA_AUTHENTICATED = 0x4
|
||||
CONNECT_DATA_IDEMPOTENT = 0x2
|
||||
CONNECT_RESUME_ON_READ_WRITE = 0x1
|
||||
CR0 = 0x0
|
||||
CR1 = 0x1000
|
||||
CR2 = 0x2000
|
||||
@@ -1169,6 +1172,11 @@ const (
|
||||
PT_WRITE_D = 0x5
|
||||
PT_WRITE_I = 0x4
|
||||
PT_WRITE_U = 0x6
|
||||
RENAME_EXCL = 0x4
|
||||
RENAME_NOFOLLOW_ANY = 0x10
|
||||
RENAME_RESERVED1 = 0x8
|
||||
RENAME_SECLUDE = 0x1
|
||||
RENAME_SWAP = 0x2
|
||||
RLIMIT_AS = 0x5
|
||||
RLIMIT_CORE = 0x4
|
||||
RLIMIT_CPU = 0x0
|
||||
@@ -1260,6 +1268,10 @@ const (
|
||||
RTV_SSTHRESH = 0x20
|
||||
RUSAGE_CHILDREN = -0x1
|
||||
RUSAGE_SELF = 0x0
|
||||
SAE_ASSOCID_ALL = 0xffffffff
|
||||
SAE_ASSOCID_ANY = 0x0
|
||||
SAE_CONNID_ALL = 0xffffffff
|
||||
SAE_CONNID_ANY = 0x0
|
||||
SCM_CREDS = 0x3
|
||||
SCM_RIGHTS = 0x1
|
||||
SCM_TIMESTAMP = 0x2
|
||||
|
||||
+141
-11
@@ -319,8 +319,12 @@ const (
|
||||
AUDIT_INTEGRITY_POLICY_RULE = 0x70f
|
||||
AUDIT_INTEGRITY_RULE = 0x70d
|
||||
AUDIT_INTEGRITY_STATUS = 0x70a
|
||||
AUDIT_INTEGRITY_USERSPACE = 0x710
|
||||
AUDIT_IPC = 0x517
|
||||
AUDIT_IPC_SET_PERM = 0x51f
|
||||
AUDIT_IPE_ACCESS = 0x58c
|
||||
AUDIT_IPE_CONFIG_CHANGE = 0x58d
|
||||
AUDIT_IPE_POLICY_LOAD = 0x58e
|
||||
AUDIT_KERNEL = 0x7d0
|
||||
AUDIT_KERNEL_OTHER = 0x524
|
||||
AUDIT_KERN_MODULE = 0x532
|
||||
@@ -457,6 +461,7 @@ const (
|
||||
B600 = 0x8
|
||||
B75 = 0x2
|
||||
B9600 = 0xd
|
||||
BCACHEFS_SUPER_MAGIC = 0xca451a4e
|
||||
BDEVFS_MAGIC = 0x62646576
|
||||
BINDERFS_SUPER_MAGIC = 0x6c6f6f70
|
||||
BINFMTFS_MAGIC = 0x42494e4d
|
||||
@@ -488,11 +493,14 @@ const (
|
||||
BPF_F_ID = 0x20
|
||||
BPF_F_NETFILTER_IP_DEFRAG = 0x1
|
||||
BPF_F_QUERY_EFFECTIVE = 0x1
|
||||
BPF_F_REDIRECT_FLAGS = 0x19
|
||||
BPF_F_REPLACE = 0x4
|
||||
BPF_F_SLEEPABLE = 0x10
|
||||
BPF_F_STRICT_ALIGNMENT = 0x1
|
||||
BPF_F_TEST_REG_INVARIANTS = 0x80
|
||||
BPF_F_TEST_RND_HI32 = 0x4
|
||||
BPF_F_TEST_RUN_ON_CPU = 0x1
|
||||
BPF_F_TEST_SKB_CHECKSUM_COMPLETE = 0x4
|
||||
BPF_F_TEST_STATE_FREQ = 0x8
|
||||
BPF_F_TEST_XDP_LIVE_FRAMES = 0x2
|
||||
BPF_F_XDP_DEV_BOUND_ONLY = 0x40
|
||||
@@ -501,6 +509,7 @@ const (
|
||||
BPF_IMM = 0x0
|
||||
BPF_IND = 0x40
|
||||
BPF_JA = 0x0
|
||||
BPF_JCOND = 0xe0
|
||||
BPF_JEQ = 0x10
|
||||
BPF_JGE = 0x30
|
||||
BPF_JGT = 0x20
|
||||
@@ -656,6 +665,9 @@ const (
|
||||
CAN_NPROTO = 0x8
|
||||
CAN_RAW = 0x1
|
||||
CAN_RAW_FILTER_MAX = 0x200
|
||||
CAN_RAW_XL_VCID_RX_FILTER = 0x4
|
||||
CAN_RAW_XL_VCID_TX_PASS = 0x2
|
||||
CAN_RAW_XL_VCID_TX_SET = 0x1
|
||||
CAN_RTR_FLAG = 0x40000000
|
||||
CAN_SFF_ID_BITS = 0xb
|
||||
CAN_SFF_MASK = 0x7ff
|
||||
@@ -832,9 +844,9 @@ const (
|
||||
DM_UUID_FLAG = 0x4000
|
||||
DM_UUID_LEN = 0x81
|
||||
DM_VERSION = 0xc138fd00
|
||||
DM_VERSION_EXTRA = "-ioctl (2023-03-01)"
|
||||
DM_VERSION_EXTRA = "-ioctl (2025-01-17)"
|
||||
DM_VERSION_MAJOR = 0x4
|
||||
DM_VERSION_MINOR = 0x30
|
||||
DM_VERSION_MINOR = 0x31
|
||||
DM_VERSION_PATCHLEVEL = 0x0
|
||||
DT_BLK = 0x6
|
||||
DT_CHR = 0x2
|
||||
@@ -923,12 +935,15 @@ const (
|
||||
EPOLL_CTL_ADD = 0x1
|
||||
EPOLL_CTL_DEL = 0x2
|
||||
EPOLL_CTL_MOD = 0x3
|
||||
EPOLL_IOC_TYPE = 0x8a
|
||||
EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2
|
||||
ESP_V4_FLOW = 0xa
|
||||
ESP_V6_FLOW = 0xc
|
||||
ETHER_FLOW = 0x12
|
||||
ETHTOOL_BUSINFO_LEN = 0x20
|
||||
ETHTOOL_EROMVERS_LEN = 0x20
|
||||
ETHTOOL_FAMILY_NAME = "ethtool"
|
||||
ETHTOOL_FAMILY_VERSION = 0x1
|
||||
ETHTOOL_FEC_AUTO = 0x2
|
||||
ETHTOOL_FEC_BASER = 0x10
|
||||
ETHTOOL_FEC_LLRS = 0x20
|
||||
@@ -936,9 +951,6 @@ const (
|
||||
ETHTOOL_FEC_OFF = 0x4
|
||||
ETHTOOL_FEC_RS = 0x8
|
||||
ETHTOOL_FLAG_ALL = 0x7
|
||||
ETHTOOL_FLAG_COMPACT_BITSETS = 0x1
|
||||
ETHTOOL_FLAG_OMIT_REPLY = 0x2
|
||||
ETHTOOL_FLAG_STATS = 0x4
|
||||
ETHTOOL_FLASHDEV = 0x33
|
||||
ETHTOOL_FLASH_MAX_FILENAME = 0x80
|
||||
ETHTOOL_FWVERS_LEN = 0x20
|
||||
@@ -1161,6 +1173,7 @@ const (
|
||||
EXTA = 0xe
|
||||
EXTB = 0xf
|
||||
F2FS_SUPER_MAGIC = 0xf2f52010
|
||||
FALLOC_FL_ALLOCATE_RANGE = 0x0
|
||||
FALLOC_FL_COLLAPSE_RANGE = 0x8
|
||||
FALLOC_FL_INSERT_RANGE = 0x20
|
||||
FALLOC_FL_KEEP_SIZE = 0x1
|
||||
@@ -1193,6 +1206,9 @@ const (
|
||||
FAN_DENY = 0x2
|
||||
FAN_ENABLE_AUDIT = 0x40
|
||||
FAN_EPIDFD = -0x2
|
||||
FAN_ERRNO_BITS = 0x8
|
||||
FAN_ERRNO_MASK = 0xff
|
||||
FAN_ERRNO_SHIFT = 0x18
|
||||
FAN_EVENT_INFO_TYPE_DFID = 0x3
|
||||
FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2
|
||||
FAN_EVENT_INFO_TYPE_ERROR = 0x5
|
||||
@@ -1200,6 +1216,7 @@ const (
|
||||
FAN_EVENT_INFO_TYPE_NEW_DFID_NAME = 0xc
|
||||
FAN_EVENT_INFO_TYPE_OLD_DFID_NAME = 0xa
|
||||
FAN_EVENT_INFO_TYPE_PIDFD = 0x4
|
||||
FAN_EVENT_INFO_TYPE_RANGE = 0x6
|
||||
FAN_EVENT_METADATA_LEN = 0x18
|
||||
FAN_EVENT_ON_CHILD = 0x8000000
|
||||
FAN_FS_ERROR = 0x8000
|
||||
@@ -1230,11 +1247,13 @@ const (
|
||||
FAN_OPEN_EXEC = 0x1000
|
||||
FAN_OPEN_EXEC_PERM = 0x40000
|
||||
FAN_OPEN_PERM = 0x10000
|
||||
FAN_PRE_ACCESS = 0x100000
|
||||
FAN_Q_OVERFLOW = 0x4000
|
||||
FAN_RENAME = 0x10000000
|
||||
FAN_REPORT_DFID_NAME = 0xc00
|
||||
FAN_REPORT_DFID_NAME_TARGET = 0x1e00
|
||||
FAN_REPORT_DIR_FID = 0x400
|
||||
FAN_REPORT_FD_ERROR = 0x2000
|
||||
FAN_REPORT_FID = 0x200
|
||||
FAN_REPORT_NAME = 0x800
|
||||
FAN_REPORT_PIDFD = 0x80
|
||||
@@ -1320,8 +1339,10 @@ const (
|
||||
FUSE_SUPER_MAGIC = 0x65735546
|
||||
FUTEXFS_SUPER_MAGIC = 0xbad1dea
|
||||
F_ADD_SEALS = 0x409
|
||||
F_CREATED_QUERY = 0x404
|
||||
F_DUPFD = 0x0
|
||||
F_DUPFD_CLOEXEC = 0x406
|
||||
F_DUPFD_QUERY = 0x403
|
||||
F_EXLCK = 0x4
|
||||
F_GETFD = 0x1
|
||||
F_GETFL = 0x3
|
||||
@@ -1338,6 +1359,7 @@ const (
|
||||
F_OFD_SETLK = 0x25
|
||||
F_OFD_SETLKW = 0x26
|
||||
F_OK = 0x0
|
||||
F_SEAL_EXEC = 0x20
|
||||
F_SEAL_FUTURE_WRITE = 0x10
|
||||
F_SEAL_GROW = 0x4
|
||||
F_SEAL_SEAL = 0x1
|
||||
@@ -1540,6 +1562,7 @@ const (
|
||||
IPPROTO_ROUTING = 0x2b
|
||||
IPPROTO_RSVP = 0x2e
|
||||
IPPROTO_SCTP = 0x84
|
||||
IPPROTO_SMC = 0x100
|
||||
IPPROTO_TCP = 0x6
|
||||
IPPROTO_TP = 0x1d
|
||||
IPPROTO_UDP = 0x11
|
||||
@@ -1612,6 +1635,8 @@ const (
|
||||
IPV6_UNICAST_IF = 0x4c
|
||||
IPV6_USER_FLOW = 0xe
|
||||
IPV6_V6ONLY = 0x1a
|
||||
IPV6_VERSION = 0x60
|
||||
IPV6_VERSION_MASK = 0xf0
|
||||
IPV6_XFRM_POLICY = 0x23
|
||||
IP_ADD_MEMBERSHIP = 0x23
|
||||
IP_ADD_SOURCE_MEMBERSHIP = 0x27
|
||||
@@ -1626,6 +1651,7 @@ const (
|
||||
IP_FREEBIND = 0xf
|
||||
IP_HDRINCL = 0x3
|
||||
IP_IPSEC_POLICY = 0x10
|
||||
IP_LOCAL_PORT_RANGE = 0x33
|
||||
IP_MAXPACKET = 0xffff
|
||||
IP_MAX_MEMBERSHIPS = 0x14
|
||||
IP_MF = 0x2000
|
||||
@@ -1652,6 +1678,7 @@ const (
|
||||
IP_PMTUDISC_OMIT = 0x5
|
||||
IP_PMTUDISC_PROBE = 0x3
|
||||
IP_PMTUDISC_WANT = 0x1
|
||||
IP_PROTOCOL = 0x34
|
||||
IP_RECVERR = 0xb
|
||||
IP_RECVERR_RFC4884 = 0x1a
|
||||
IP_RECVFRAGSIZE = 0x19
|
||||
@@ -1697,6 +1724,8 @@ const (
|
||||
KEXEC_ARCH_S390 = 0x160000
|
||||
KEXEC_ARCH_SH = 0x2a0000
|
||||
KEXEC_ARCH_X86_64 = 0x3e0000
|
||||
KEXEC_CRASH_HOTPLUG_SUPPORT = 0x8
|
||||
KEXEC_FILE_DEBUG = 0x8
|
||||
KEXEC_FILE_NO_INITRAMFS = 0x4
|
||||
KEXEC_FILE_ON_CRASH = 0x2
|
||||
KEXEC_FILE_UNLOAD = 0x1
|
||||
@@ -1771,6 +1800,7 @@ const (
|
||||
KEY_SPEC_USER_KEYRING = -0x4
|
||||
KEY_SPEC_USER_SESSION_KEYRING = -0x5
|
||||
LANDLOCK_ACCESS_FS_EXECUTE = 0x1
|
||||
LANDLOCK_ACCESS_FS_IOCTL_DEV = 0x8000
|
||||
LANDLOCK_ACCESS_FS_MAKE_BLOCK = 0x800
|
||||
LANDLOCK_ACCESS_FS_MAKE_CHAR = 0x40
|
||||
LANDLOCK_ACCESS_FS_MAKE_DIR = 0x80
|
||||
@@ -1788,6 +1818,8 @@ const (
|
||||
LANDLOCK_ACCESS_NET_BIND_TCP = 0x1
|
||||
LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2
|
||||
LANDLOCK_CREATE_RULESET_VERSION = 0x1
|
||||
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = 0x1
|
||||
LANDLOCK_SCOPE_SIGNAL = 0x2
|
||||
LINUX_REBOOT_CMD_CAD_OFF = 0x0
|
||||
LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef
|
||||
LINUX_REBOOT_CMD_HALT = 0xcdef0123
|
||||
@@ -1849,9 +1881,23 @@ const (
|
||||
MADV_UNMERGEABLE = 0xd
|
||||
MADV_WILLNEED = 0x3
|
||||
MADV_WIPEONFORK = 0x12
|
||||
MAP_DROPPABLE = 0x8
|
||||
MAP_FILE = 0x0
|
||||
MAP_FIXED = 0x10
|
||||
MAP_FIXED_NOREPLACE = 0x100000
|
||||
MAP_HUGE_16GB = 0x88000000
|
||||
MAP_HUGE_16KB = 0x38000000
|
||||
MAP_HUGE_16MB = 0x60000000
|
||||
MAP_HUGE_1GB = 0x78000000
|
||||
MAP_HUGE_1MB = 0x50000000
|
||||
MAP_HUGE_256MB = 0x70000000
|
||||
MAP_HUGE_2GB = 0x7c000000
|
||||
MAP_HUGE_2MB = 0x54000000
|
||||
MAP_HUGE_32MB = 0x64000000
|
||||
MAP_HUGE_512KB = 0x4c000000
|
||||
MAP_HUGE_512MB = 0x74000000
|
||||
MAP_HUGE_64KB = 0x40000000
|
||||
MAP_HUGE_8MB = 0x5c000000
|
||||
MAP_HUGE_MASK = 0x3f
|
||||
MAP_HUGE_SHIFT = 0x1a
|
||||
MAP_PRIVATE = 0x2
|
||||
@@ -1898,6 +1944,9 @@ const (
|
||||
MNT_DETACH = 0x2
|
||||
MNT_EXPIRE = 0x4
|
||||
MNT_FORCE = 0x1
|
||||
MNT_ID_REQ_SIZE_VER0 = 0x18
|
||||
MNT_ID_REQ_SIZE_VER1 = 0x20
|
||||
MNT_NS_INFO_SIZE_VER0 = 0x10
|
||||
MODULE_INIT_COMPRESSED_FILE = 0x4
|
||||
MODULE_INIT_IGNORE_MODVERSIONS = 0x1
|
||||
MODULE_INIT_IGNORE_VERMAGIC = 0x2
|
||||
@@ -1933,6 +1982,7 @@ const (
|
||||
MSG_PEEK = 0x2
|
||||
MSG_PROXY = 0x10
|
||||
MSG_RST = 0x1000
|
||||
MSG_SOCK_DEVMEM = 0x2000000
|
||||
MSG_SYN = 0x400
|
||||
MSG_TRUNC = 0x20
|
||||
MSG_TRYHARD = 0x4
|
||||
@@ -2049,6 +2099,7 @@ const (
|
||||
NFC_ATR_REQ_MAXSIZE = 0x40
|
||||
NFC_ATR_RES_GB_MAXSIZE = 0x2f
|
||||
NFC_ATR_RES_MAXSIZE = 0x40
|
||||
NFC_ATS_MAXSIZE = 0x14
|
||||
NFC_COMM_ACTIVE = 0x0
|
||||
NFC_COMM_PASSIVE = 0x1
|
||||
NFC_DEVICE_NAME_MAXSIZE = 0x8
|
||||
@@ -2129,6 +2180,7 @@ const (
|
||||
NFNL_SUBSYS_QUEUE = 0x3
|
||||
NFNL_SUBSYS_ULOG = 0x4
|
||||
NFS_SUPER_MAGIC = 0x6969
|
||||
NFT_BITWISE_BOOL = 0x0
|
||||
NFT_CHAIN_FLAGS = 0x7
|
||||
NFT_CHAIN_MAXNAMELEN = 0x100
|
||||
NFT_CT_MAX = 0x17
|
||||
@@ -2163,10 +2215,10 @@ const (
|
||||
NFT_REG_SIZE = 0x10
|
||||
NFT_REJECT_ICMPX_MAX = 0x3
|
||||
NFT_RT_MAX = 0x4
|
||||
NFT_SECMARK_CTX_MAXLEN = 0x100
|
||||
NFT_SECMARK_CTX_MAXLEN = 0x1000
|
||||
NFT_SET_MAXNAMELEN = 0x100
|
||||
NFT_SOCKET_MAX = 0x3
|
||||
NFT_TABLE_F_MASK = 0x3
|
||||
NFT_TABLE_F_MASK = 0x7
|
||||
NFT_TABLE_MAXNAMELEN = 0x100
|
||||
NFT_TRACETYPE_MAX = 0x3
|
||||
NFT_TUNNEL_F_MASK = 0x7
|
||||
@@ -2302,6 +2354,7 @@ const (
|
||||
PERF_AUX_FLAG_PARTIAL = 0x4
|
||||
PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK = 0xff00
|
||||
PERF_AUX_FLAG_TRUNCATED = 0x1
|
||||
PERF_BRANCH_ENTRY_INFO_BITS_MAX = 0x21
|
||||
PERF_BR_ARM64_DEBUG_DATA = 0x7
|
||||
PERF_BR_ARM64_DEBUG_EXIT = 0x5
|
||||
PERF_BR_ARM64_DEBUG_HALT = 0x4
|
||||
@@ -2331,9 +2384,11 @@ const (
|
||||
PERF_MEM_LVLNUM_IO = 0xa
|
||||
PERF_MEM_LVLNUM_L1 = 0x1
|
||||
PERF_MEM_LVLNUM_L2 = 0x2
|
||||
PERF_MEM_LVLNUM_L2_MHB = 0x5
|
||||
PERF_MEM_LVLNUM_L3 = 0x3
|
||||
PERF_MEM_LVLNUM_L4 = 0x4
|
||||
PERF_MEM_LVLNUM_LFB = 0xc
|
||||
PERF_MEM_LVLNUM_MSC = 0x6
|
||||
PERF_MEM_LVLNUM_NA = 0xf
|
||||
PERF_MEM_LVLNUM_PMEM = 0xe
|
||||
PERF_MEM_LVLNUM_RAM = 0xd
|
||||
@@ -2399,12 +2454,14 @@ const (
|
||||
PERF_RECORD_MISC_USER = 0x2
|
||||
PERF_SAMPLE_BRANCH_PLM_ALL = 0x7
|
||||
PERF_SAMPLE_WEIGHT_TYPE = 0x1004000
|
||||
PID_FS_MAGIC = 0x50494446
|
||||
PIPEFS_MAGIC = 0x50495045
|
||||
PPPIOCGNPMODE = 0xc008744c
|
||||
PPPIOCNEWUNIT = 0xc004743e
|
||||
PRIO_PGRP = 0x1
|
||||
PRIO_PROCESS = 0x0
|
||||
PRIO_USER = 0x2
|
||||
PROCFS_IOCTL_MAGIC = 'f'
|
||||
PROC_SUPER_MAGIC = 0x9fa0
|
||||
PROT_EXEC = 0x4
|
||||
PROT_GROWSDOWN = 0x1000000
|
||||
@@ -2452,6 +2509,7 @@ const (
|
||||
PR_GET_PDEATHSIG = 0x2
|
||||
PR_GET_SECCOMP = 0x15
|
||||
PR_GET_SECUREBITS = 0x1b
|
||||
PR_GET_SHADOW_STACK_STATUS = 0x4a
|
||||
PR_GET_SPECULATION_CTRL = 0x34
|
||||
PR_GET_TAGGED_ADDR_CTRL = 0x38
|
||||
PR_GET_THP_DISABLE = 0x2a
|
||||
@@ -2460,6 +2518,7 @@ const (
|
||||
PR_GET_TIMING = 0xd
|
||||
PR_GET_TSC = 0x19
|
||||
PR_GET_UNALIGN = 0x5
|
||||
PR_LOCK_SHADOW_STACK_STATUS = 0x4c
|
||||
PR_MCE_KILL = 0x21
|
||||
PR_MCE_KILL_CLEAR = 0x0
|
||||
PR_MCE_KILL_DEFAULT = 0x2
|
||||
@@ -2486,6 +2545,25 @@ const (
|
||||
PR_PAC_GET_ENABLED_KEYS = 0x3d
|
||||
PR_PAC_RESET_KEYS = 0x36
|
||||
PR_PAC_SET_ENABLED_KEYS = 0x3c
|
||||
PR_PMLEN_MASK = 0x7f000000
|
||||
PR_PMLEN_SHIFT = 0x18
|
||||
PR_PPC_DEXCR_CTRL_CLEAR = 0x4
|
||||
PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC = 0x10
|
||||
PR_PPC_DEXCR_CTRL_EDITABLE = 0x1
|
||||
PR_PPC_DEXCR_CTRL_MASK = 0x1f
|
||||
PR_PPC_DEXCR_CTRL_SET = 0x2
|
||||
PR_PPC_DEXCR_CTRL_SET_ONEXEC = 0x8
|
||||
PR_PPC_DEXCR_IBRTPD = 0x1
|
||||
PR_PPC_DEXCR_NPHIE = 0x3
|
||||
PR_PPC_DEXCR_SBHE = 0x0
|
||||
PR_PPC_DEXCR_SRAPD = 0x2
|
||||
PR_PPC_GET_DEXCR = 0x48
|
||||
PR_PPC_SET_DEXCR = 0x49
|
||||
PR_RISCV_CTX_SW_FENCEI_OFF = 0x1
|
||||
PR_RISCV_CTX_SW_FENCEI_ON = 0x0
|
||||
PR_RISCV_SCOPE_PER_PROCESS = 0x0
|
||||
PR_RISCV_SCOPE_PER_THREAD = 0x1
|
||||
PR_RISCV_SET_ICACHE_FLUSH_CTX = 0x47
|
||||
PR_RISCV_V_GET_CONTROL = 0x46
|
||||
PR_RISCV_V_SET_CONTROL = 0x45
|
||||
PR_RISCV_V_VSTATE_CTRL_CUR_MASK = 0x3
|
||||
@@ -2536,6 +2614,7 @@ const (
|
||||
PR_SET_PTRACER = 0x59616d61
|
||||
PR_SET_SECCOMP = 0x16
|
||||
PR_SET_SECUREBITS = 0x1c
|
||||
PR_SET_SHADOW_STACK_STATUS = 0x4b
|
||||
PR_SET_SPECULATION_CTRL = 0x35
|
||||
PR_SET_SYSCALL_USER_DISPATCH = 0x3b
|
||||
PR_SET_TAGGED_ADDR_CTRL = 0x37
|
||||
@@ -2546,6 +2625,9 @@ const (
|
||||
PR_SET_UNALIGN = 0x6
|
||||
PR_SET_VMA = 0x53564d41
|
||||
PR_SET_VMA_ANON_NAME = 0x0
|
||||
PR_SHADOW_STACK_ENABLE = 0x1
|
||||
PR_SHADOW_STACK_PUSH = 0x4
|
||||
PR_SHADOW_STACK_WRITE = 0x2
|
||||
PR_SME_GET_VL = 0x40
|
||||
PR_SME_SET_VL = 0x3f
|
||||
PR_SME_SET_VL_ONEXEC = 0x40000
|
||||
@@ -2577,6 +2659,28 @@ const (
|
||||
PR_UNALIGN_NOPRINT = 0x1
|
||||
PR_UNALIGN_SIGBUS = 0x2
|
||||
PSTOREFS_MAGIC = 0x6165676c
|
||||
PTP_CLK_MAGIC = '='
|
||||
PTP_ENABLE_FEATURE = 0x1
|
||||
PTP_EXTTS_EDGES = 0x6
|
||||
PTP_EXTTS_EVENT_VALID = 0x1
|
||||
PTP_EXTTS_V1_VALID_FLAGS = 0x7
|
||||
PTP_EXTTS_VALID_FLAGS = 0x1f
|
||||
PTP_EXT_OFFSET = 0x10
|
||||
PTP_FALLING_EDGE = 0x4
|
||||
PTP_MAX_SAMPLES = 0x19
|
||||
PTP_PEROUT_DUTY_CYCLE = 0x2
|
||||
PTP_PEROUT_ONE_SHOT = 0x1
|
||||
PTP_PEROUT_PHASE = 0x4
|
||||
PTP_PEROUT_V1_VALID_FLAGS = 0x0
|
||||
PTP_PEROUT_VALID_FLAGS = 0x7
|
||||
PTP_PIN_GETFUNC = 0xc0603d06
|
||||
PTP_PIN_GETFUNC2 = 0xc0603d0f
|
||||
PTP_RISING_EDGE = 0x2
|
||||
PTP_STRICT_FLAGS = 0x8
|
||||
PTP_SYS_OFFSET_EXTENDED = 0xc4c03d09
|
||||
PTP_SYS_OFFSET_EXTENDED2 = 0xc4c03d12
|
||||
PTP_SYS_OFFSET_PRECISE = 0xc0403d08
|
||||
PTP_SYS_OFFSET_PRECISE2 = 0xc0403d11
|
||||
PTRACE_ATTACH = 0x10
|
||||
PTRACE_CONT = 0x7
|
||||
PTRACE_DETACH = 0x11
|
||||
@@ -2691,7 +2795,7 @@ const (
|
||||
RTAX_UNSPEC = 0x0
|
||||
RTAX_WINDOW = 0x3
|
||||
RTA_ALIGNTO = 0x4
|
||||
RTA_MAX = 0x1e
|
||||
RTA_MAX = 0x1f
|
||||
RTCF_DIRECTSRC = 0x4000000
|
||||
RTCF_DOREDIRECT = 0x1000000
|
||||
RTCF_LOG = 0x2000000
|
||||
@@ -2768,10 +2872,12 @@ const (
|
||||
RTM_DELACTION = 0x31
|
||||
RTM_DELADDR = 0x15
|
||||
RTM_DELADDRLABEL = 0x49
|
||||
RTM_DELANYCAST = 0x3d
|
||||
RTM_DELCHAIN = 0x65
|
||||
RTM_DELLINK = 0x11
|
||||
RTM_DELLINKPROP = 0x6d
|
||||
RTM_DELMDB = 0x55
|
||||
RTM_DELMULTICAST = 0x39
|
||||
RTM_DELNEIGH = 0x1d
|
||||
RTM_DELNETCONF = 0x51
|
||||
RTM_DELNEXTHOP = 0x69
|
||||
@@ -2821,11 +2927,13 @@ const (
|
||||
RTM_NEWACTION = 0x30
|
||||
RTM_NEWADDR = 0x14
|
||||
RTM_NEWADDRLABEL = 0x48
|
||||
RTM_NEWANYCAST = 0x3c
|
||||
RTM_NEWCACHEREPORT = 0x60
|
||||
RTM_NEWCHAIN = 0x64
|
||||
RTM_NEWLINK = 0x10
|
||||
RTM_NEWLINKPROP = 0x6c
|
||||
RTM_NEWMDB = 0x54
|
||||
RTM_NEWMULTICAST = 0x38
|
||||
RTM_NEWNDUSEROPT = 0x44
|
||||
RTM_NEWNEIGH = 0x1c
|
||||
RTM_NEWNEIGHTBL = 0x40
|
||||
@@ -2833,7 +2941,6 @@ const (
|
||||
RTM_NEWNEXTHOP = 0x68
|
||||
RTM_NEWNEXTHOPBUCKET = 0x74
|
||||
RTM_NEWNSID = 0x58
|
||||
RTM_NEWNVLAN = 0x70
|
||||
RTM_NEWPREFIX = 0x34
|
||||
RTM_NEWQDISC = 0x24
|
||||
RTM_NEWROUTE = 0x18
|
||||
@@ -2842,6 +2949,7 @@ const (
|
||||
RTM_NEWTCLASS = 0x28
|
||||
RTM_NEWTFILTER = 0x2c
|
||||
RTM_NEWTUNNEL = 0x78
|
||||
RTM_NEWVLAN = 0x70
|
||||
RTM_NR_FAMILIES = 0x1b
|
||||
RTM_NR_MSGTYPES = 0x6c
|
||||
RTM_SETDCB = 0x4f
|
||||
@@ -2890,14 +2998,18 @@ const (
|
||||
RUSAGE_SELF = 0x0
|
||||
RUSAGE_THREAD = 0x1
|
||||
RWF_APPEND = 0x10
|
||||
RWF_ATOMIC = 0x40
|
||||
RWF_DONTCACHE = 0x80
|
||||
RWF_DSYNC = 0x2
|
||||
RWF_HIPRI = 0x1
|
||||
RWF_NOAPPEND = 0x20
|
||||
RWF_NOWAIT = 0x8
|
||||
RWF_SUPPORTED = 0x1f
|
||||
RWF_SUPPORTED = 0xff
|
||||
RWF_SYNC = 0x4
|
||||
RWF_WRITE_LIFE_NOT_SET = 0x0
|
||||
SCHED_BATCH = 0x3
|
||||
SCHED_DEADLINE = 0x6
|
||||
SCHED_EXT = 0x7
|
||||
SCHED_FIFO = 0x1
|
||||
SCHED_FLAG_ALL = 0x7f
|
||||
SCHED_FLAG_DL_OVERRUN = 0x4
|
||||
@@ -2914,7 +3026,9 @@ const (
|
||||
SCHED_RESET_ON_FORK = 0x40000000
|
||||
SCHED_RR = 0x2
|
||||
SCM_CREDENTIALS = 0x2
|
||||
SCM_PIDFD = 0x4
|
||||
SCM_RIGHTS = 0x1
|
||||
SCM_SECURITY = 0x3
|
||||
SCM_TIMESTAMP = 0x1d
|
||||
SC_LOG_FLUSH = 0x100000
|
||||
SECCOMP_ADDFD_FLAG_SEND = 0x2
|
||||
@@ -3047,6 +3161,8 @@ const (
|
||||
SIOCSMIIREG = 0x8949
|
||||
SIOCSRARP = 0x8962
|
||||
SIOCWANDEV = 0x894a
|
||||
SK_DIAG_BPF_STORAGE_MAX = 0x3
|
||||
SK_DIAG_BPF_STORAGE_REQ_MAX = 0x1
|
||||
SMACK_MAGIC = 0x43415d53
|
||||
SMART_AUTOSAVE = 0xd2
|
||||
SMART_AUTO_OFFLINE = 0xdb
|
||||
@@ -3067,6 +3183,8 @@ const (
|
||||
SOCKFS_MAGIC = 0x534f434b
|
||||
SOCK_BUF_LOCK_MASK = 0x3
|
||||
SOCK_DCCP = 0x6
|
||||
SOCK_DESTROY = 0x15
|
||||
SOCK_DIAG_BY_FAMILY = 0x14
|
||||
SOCK_IOC_TYPE = 0x89
|
||||
SOCK_PACKET = 0xa
|
||||
SOCK_RAW = 0x3
|
||||
@@ -3160,20 +3278,25 @@ const (
|
||||
STATX_ATTR_MOUNT_ROOT = 0x2000
|
||||
STATX_ATTR_NODUMP = 0x40
|
||||
STATX_ATTR_VERITY = 0x100000
|
||||
STATX_ATTR_WRITE_ATOMIC = 0x400000
|
||||
STATX_BASIC_STATS = 0x7ff
|
||||
STATX_BLOCKS = 0x400
|
||||
STATX_BTIME = 0x800
|
||||
STATX_CTIME = 0x80
|
||||
STATX_DIOALIGN = 0x2000
|
||||
STATX_DIO_READ_ALIGN = 0x20000
|
||||
STATX_GID = 0x10
|
||||
STATX_INO = 0x100
|
||||
STATX_MNT_ID = 0x1000
|
||||
STATX_MNT_ID_UNIQUE = 0x4000
|
||||
STATX_MODE = 0x2
|
||||
STATX_MTIME = 0x40
|
||||
STATX_NLINK = 0x4
|
||||
STATX_SIZE = 0x200
|
||||
STATX_SUBVOL = 0x8000
|
||||
STATX_TYPE = 0x1
|
||||
STATX_UID = 0x8
|
||||
STATX_WRITE_ATOMIC = 0x10000
|
||||
STATX__RESERVED = 0x80000000
|
||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||
@@ -3213,7 +3336,7 @@ const (
|
||||
TASKSTATS_GENL_NAME = "TASKSTATS"
|
||||
TASKSTATS_GENL_VERSION = 0x1
|
||||
TASKSTATS_TYPE_MAX = 0x6
|
||||
TASKSTATS_VERSION = 0xe
|
||||
TASKSTATS_VERSION = 0xf
|
||||
TCIFLUSH = 0x0
|
||||
TCIOFF = 0x2
|
||||
TCIOFLUSH = 0x2
|
||||
@@ -3255,6 +3378,7 @@ const (
|
||||
TCP_MAX_WINSHIFT = 0xe
|
||||
TCP_MD5SIG = 0xe
|
||||
TCP_MD5SIG_EXT = 0x20
|
||||
TCP_MD5SIG_FLAG_IFINDEX = 0x2
|
||||
TCP_MD5SIG_FLAG_PREFIX = 0x1
|
||||
TCP_MD5SIG_MAXKEYLEN = 0x50
|
||||
TCP_MSS = 0x200
|
||||
@@ -3393,6 +3517,7 @@ const (
|
||||
TP_STATUS_WRONG_FORMAT = 0x4
|
||||
TRACEFS_MAGIC = 0x74726163
|
||||
TS_COMM_LEN = 0x20
|
||||
UBI_IOCECNFO = 0xc01c6f06
|
||||
UDF_SUPER_MAGIC = 0x15013346
|
||||
UDP_CORK = 0x1
|
||||
UDP_ENCAP = 0x64
|
||||
@@ -3562,12 +3687,17 @@ const (
|
||||
XDP_RX_RING = 0x2
|
||||
XDP_SHARED_UMEM = 0x1
|
||||
XDP_STATISTICS = 0x7
|
||||
XDP_TXMD_FLAGS_CHECKSUM = 0x2
|
||||
XDP_TXMD_FLAGS_TIMESTAMP = 0x1
|
||||
XDP_TX_METADATA = 0x2
|
||||
XDP_TX_RING = 0x3
|
||||
XDP_UMEM_COMPLETION_RING = 0x6
|
||||
XDP_UMEM_FILL_RING = 0x5
|
||||
XDP_UMEM_PGOFF_COMPLETION_RING = 0x180000000
|
||||
XDP_UMEM_PGOFF_FILL_RING = 0x100000000
|
||||
XDP_UMEM_REG = 0x4
|
||||
XDP_UMEM_TX_METADATA_LEN = 0x4
|
||||
XDP_UMEM_TX_SW_CSUM = 0x2
|
||||
XDP_UMEM_UNALIGNED_CHUNK_FLAG = 0x1
|
||||
XDP_USE_NEED_WAKEUP = 0x8
|
||||
XDP_USE_SG = 0x10
|
||||
|
||||
+32
@@ -78,6 +78,8 @@ const (
|
||||
ECHOPRT = 0x400
|
||||
EFD_CLOEXEC = 0x80000
|
||||
EFD_NONBLOCK = 0x800
|
||||
EPIOCGPARAMS = 0x80088a02
|
||||
EPIOCSPARAMS = 0x40088a01
|
||||
EPOLL_CLOEXEC = 0x80000
|
||||
EXTPROC = 0x10000
|
||||
FF1 = 0x8000
|
||||
@@ -107,17 +109,21 @@ const (
|
||||
HIDIOCGRAWINFO = 0x80084803
|
||||
HIDIOCGRDESC = 0x90044802
|
||||
HIDIOCGRDESCSIZE = 0x80044801
|
||||
HIDIOCREVOKE = 0x4004480d
|
||||
HUPCL = 0x400
|
||||
ICANON = 0x2
|
||||
IEXTEN = 0x8000
|
||||
IN_CLOEXEC = 0x80000
|
||||
IN_NONBLOCK = 0x800
|
||||
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
|
||||
IPV6_FLOWINFO_MASK = 0xffffff0f
|
||||
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
||||
ISIG = 0x1
|
||||
IUCLC = 0x200
|
||||
IXOFF = 0x1000
|
||||
IXON = 0x400
|
||||
MAP_32BIT = 0x40
|
||||
MAP_ABOVE4G = 0x80
|
||||
MAP_ANON = 0x20
|
||||
MAP_ANONYMOUS = 0x20
|
||||
MAP_DENYWRITE = 0x800
|
||||
@@ -150,9 +156,14 @@ const (
|
||||
NFDBITS = 0x20
|
||||
NLDLY = 0x100
|
||||
NOFLSH = 0x80
|
||||
NS_GET_MNTNS_ID = 0x8008b705
|
||||
NS_GET_NSTYPE = 0xb703
|
||||
NS_GET_OWNER_UID = 0xb704
|
||||
NS_GET_PARENT = 0xb702
|
||||
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||
NS_GET_USERNS = 0xb701
|
||||
OLCUC = 0x2
|
||||
ONLCR = 0x4
|
||||
@@ -229,6 +240,20 @@ const (
|
||||
PPPIOCUNBRIDGECHAN = 0x7434
|
||||
PPPIOCXFERUNIT = 0x744e
|
||||
PR_SET_PTRACER_ANY = 0xffffffff
|
||||
PTP_CLOCK_GETCAPS = 0x80503d01
|
||||
PTP_CLOCK_GETCAPS2 = 0x80503d0a
|
||||
PTP_ENABLE_PPS = 0x40043d04
|
||||
PTP_ENABLE_PPS2 = 0x40043d0d
|
||||
PTP_EXTTS_REQUEST = 0x40103d02
|
||||
PTP_EXTTS_REQUEST2 = 0x40103d0b
|
||||
PTP_MASK_CLEAR_ALL = 0x3d13
|
||||
PTP_MASK_EN_SINGLE = 0x40043d14
|
||||
PTP_PEROUT_REQUEST = 0x40383d03
|
||||
PTP_PEROUT_REQUEST2 = 0x40383d0c
|
||||
PTP_PIN_SETFUNC = 0x40603d07
|
||||
PTP_PIN_SETFUNC2 = 0x40603d10
|
||||
PTP_SYS_OFFSET = 0x43403d05
|
||||
PTP_SYS_OFFSET2 = 0x43403d0e
|
||||
PTRACE_GETFPREGS = 0xe
|
||||
PTRACE_GETFPXREGS = 0x12
|
||||
PTRACE_GET_THREAD_AREA = 0x19
|
||||
@@ -275,10 +300,13 @@ const (
|
||||
RTC_WIE_ON = 0x700f
|
||||
RTC_WKALM_RD = 0x80287010
|
||||
RTC_WKALM_SET = 0x4028700f
|
||||
SCM_DEVMEM_DMABUF = 0x4f
|
||||
SCM_DEVMEM_LINEAR = 0x4e
|
||||
SCM_TIMESTAMPING = 0x25
|
||||
SCM_TIMESTAMPING_OPT_STATS = 0x36
|
||||
SCM_TIMESTAMPING_PKTINFO = 0x3a
|
||||
SCM_TIMESTAMPNS = 0x23
|
||||
SCM_TS_OPT_ID = 0x51
|
||||
SCM_TXTIME = 0x3d
|
||||
SCM_WIFI_STATUS = 0x29
|
||||
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||
@@ -313,6 +341,9 @@ const (
|
||||
SO_CNX_ADVICE = 0x35
|
||||
SO_COOKIE = 0x39
|
||||
SO_DETACH_REUSEPORT_BPF = 0x44
|
||||
SO_DEVMEM_DMABUF = 0x4f
|
||||
SO_DEVMEM_DONTNEED = 0x50
|
||||
SO_DEVMEM_LINEAR = 0x4e
|
||||
SO_DOMAIN = 0x27
|
||||
SO_DONTROUTE = 0x5
|
||||
SO_ERROR = 0x4
|
||||
@@ -341,6 +372,7 @@ const (
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVPRIORITY = 0x52
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
|
||||
+32
@@ -78,6 +78,8 @@ const (
|
||||
ECHOPRT = 0x400
|
||||
EFD_CLOEXEC = 0x80000
|
||||
EFD_NONBLOCK = 0x800
|
||||
EPIOCGPARAMS = 0x80088a02
|
||||
EPIOCSPARAMS = 0x40088a01
|
||||
EPOLL_CLOEXEC = 0x80000
|
||||
EXTPROC = 0x10000
|
||||
FF1 = 0x8000
|
||||
@@ -107,17 +109,21 @@ const (
|
||||
HIDIOCGRAWINFO = 0x80084803
|
||||
HIDIOCGRDESC = 0x90044802
|
||||
HIDIOCGRDESCSIZE = 0x80044801
|
||||
HIDIOCREVOKE = 0x4004480d
|
||||
HUPCL = 0x400
|
||||
ICANON = 0x2
|
||||
IEXTEN = 0x8000
|
||||
IN_CLOEXEC = 0x80000
|
||||
IN_NONBLOCK = 0x800
|
||||
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
|
||||
IPV6_FLOWINFO_MASK = 0xffffff0f
|
||||
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
||||
ISIG = 0x1
|
||||
IUCLC = 0x200
|
||||
IXOFF = 0x1000
|
||||
IXON = 0x400
|
||||
MAP_32BIT = 0x40
|
||||
MAP_ABOVE4G = 0x80
|
||||
MAP_ANON = 0x20
|
||||
MAP_ANONYMOUS = 0x20
|
||||
MAP_DENYWRITE = 0x800
|
||||
@@ -150,9 +156,14 @@ const (
|
||||
NFDBITS = 0x40
|
||||
NLDLY = 0x100
|
||||
NOFLSH = 0x80
|
||||
NS_GET_MNTNS_ID = 0x8008b705
|
||||
NS_GET_NSTYPE = 0xb703
|
||||
NS_GET_OWNER_UID = 0xb704
|
||||
NS_GET_PARENT = 0xb702
|
||||
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||
NS_GET_USERNS = 0xb701
|
||||
OLCUC = 0x2
|
||||
ONLCR = 0x4
|
||||
@@ -229,6 +240,20 @@ const (
|
||||
PPPIOCUNBRIDGECHAN = 0x7434
|
||||
PPPIOCXFERUNIT = 0x744e
|
||||
PR_SET_PTRACER_ANY = 0xffffffffffffffff
|
||||
PTP_CLOCK_GETCAPS = 0x80503d01
|
||||
PTP_CLOCK_GETCAPS2 = 0x80503d0a
|
||||
PTP_ENABLE_PPS = 0x40043d04
|
||||
PTP_ENABLE_PPS2 = 0x40043d0d
|
||||
PTP_EXTTS_REQUEST = 0x40103d02
|
||||
PTP_EXTTS_REQUEST2 = 0x40103d0b
|
||||
PTP_MASK_CLEAR_ALL = 0x3d13
|
||||
PTP_MASK_EN_SINGLE = 0x40043d14
|
||||
PTP_PEROUT_REQUEST = 0x40383d03
|
||||
PTP_PEROUT_REQUEST2 = 0x40383d0c
|
||||
PTP_PIN_SETFUNC = 0x40603d07
|
||||
PTP_PIN_SETFUNC2 = 0x40603d10
|
||||
PTP_SYS_OFFSET = 0x43403d05
|
||||
PTP_SYS_OFFSET2 = 0x43403d0e
|
||||
PTRACE_ARCH_PRCTL = 0x1e
|
||||
PTRACE_GETFPREGS = 0xe
|
||||
PTRACE_GETFPXREGS = 0x12
|
||||
@@ -276,10 +301,13 @@ const (
|
||||
RTC_WIE_ON = 0x700f
|
||||
RTC_WKALM_RD = 0x80287010
|
||||
RTC_WKALM_SET = 0x4028700f
|
||||
SCM_DEVMEM_DMABUF = 0x4f
|
||||
SCM_DEVMEM_LINEAR = 0x4e
|
||||
SCM_TIMESTAMPING = 0x25
|
||||
SCM_TIMESTAMPING_OPT_STATS = 0x36
|
||||
SCM_TIMESTAMPING_PKTINFO = 0x3a
|
||||
SCM_TIMESTAMPNS = 0x23
|
||||
SCM_TS_OPT_ID = 0x51
|
||||
SCM_TXTIME = 0x3d
|
||||
SCM_WIFI_STATUS = 0x29
|
||||
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||
@@ -314,6 +342,9 @@ const (
|
||||
SO_CNX_ADVICE = 0x35
|
||||
SO_COOKIE = 0x39
|
||||
SO_DETACH_REUSEPORT_BPF = 0x44
|
||||
SO_DEVMEM_DMABUF = 0x4f
|
||||
SO_DEVMEM_DONTNEED = 0x50
|
||||
SO_DEVMEM_LINEAR = 0x4e
|
||||
SO_DOMAIN = 0x27
|
||||
SO_DONTROUTE = 0x5
|
||||
SO_ERROR = 0x4
|
||||
@@ -342,6 +373,7 @@ const (
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVPRIORITY = 0x52
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
|
||||
+31
@@ -78,6 +78,8 @@ const (
|
||||
ECHOPRT = 0x400
|
||||
EFD_CLOEXEC = 0x80000
|
||||
EFD_NONBLOCK = 0x800
|
||||
EPIOCGPARAMS = 0x80088a02
|
||||
EPIOCSPARAMS = 0x40088a01
|
||||
EPOLL_CLOEXEC = 0x80000
|
||||
EXTPROC = 0x10000
|
||||
FF1 = 0x8000
|
||||
@@ -106,12 +108,15 @@ const (
|
||||
HIDIOCGRAWINFO = 0x80084803
|
||||
HIDIOCGRDESC = 0x90044802
|
||||
HIDIOCGRDESCSIZE = 0x80044801
|
||||
HIDIOCREVOKE = 0x4004480d
|
||||
HUPCL = 0x400
|
||||
ICANON = 0x2
|
||||
IEXTEN = 0x8000
|
||||
IN_CLOEXEC = 0x80000
|
||||
IN_NONBLOCK = 0x800
|
||||
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
|
||||
IPV6_FLOWINFO_MASK = 0xffffff0f
|
||||
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
||||
ISIG = 0x1
|
||||
IUCLC = 0x200
|
||||
IXOFF = 0x1000
|
||||
@@ -148,9 +153,14 @@ const (
|
||||
NFDBITS = 0x20
|
||||
NLDLY = 0x100
|
||||
NOFLSH = 0x80
|
||||
NS_GET_MNTNS_ID = 0x8008b705
|
||||
NS_GET_NSTYPE = 0xb703
|
||||
NS_GET_OWNER_UID = 0xb704
|
||||
NS_GET_PARENT = 0xb702
|
||||
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||
NS_GET_USERNS = 0xb701
|
||||
OLCUC = 0x2
|
||||
ONLCR = 0x4
|
||||
@@ -227,6 +237,20 @@ const (
|
||||
PPPIOCUNBRIDGECHAN = 0x7434
|
||||
PPPIOCXFERUNIT = 0x744e
|
||||
PR_SET_PTRACER_ANY = 0xffffffff
|
||||
PTP_CLOCK_GETCAPS = 0x80503d01
|
||||
PTP_CLOCK_GETCAPS2 = 0x80503d0a
|
||||
PTP_ENABLE_PPS = 0x40043d04
|
||||
PTP_ENABLE_PPS2 = 0x40043d0d
|
||||
PTP_EXTTS_REQUEST = 0x40103d02
|
||||
PTP_EXTTS_REQUEST2 = 0x40103d0b
|
||||
PTP_MASK_CLEAR_ALL = 0x3d13
|
||||
PTP_MASK_EN_SINGLE = 0x40043d14
|
||||
PTP_PEROUT_REQUEST = 0x40383d03
|
||||
PTP_PEROUT_REQUEST2 = 0x40383d0c
|
||||
PTP_PIN_SETFUNC = 0x40603d07
|
||||
PTP_PIN_SETFUNC2 = 0x40603d10
|
||||
PTP_SYS_OFFSET = 0x43403d05
|
||||
PTP_SYS_OFFSET2 = 0x43403d0e
|
||||
PTRACE_GETCRUNCHREGS = 0x19
|
||||
PTRACE_GETFDPIC = 0x1f
|
||||
PTRACE_GETFDPIC_EXEC = 0x0
|
||||
@@ -282,10 +306,13 @@ const (
|
||||
RTC_WIE_ON = 0x700f
|
||||
RTC_WKALM_RD = 0x80287010
|
||||
RTC_WKALM_SET = 0x4028700f
|
||||
SCM_DEVMEM_DMABUF = 0x4f
|
||||
SCM_DEVMEM_LINEAR = 0x4e
|
||||
SCM_TIMESTAMPING = 0x25
|
||||
SCM_TIMESTAMPING_OPT_STATS = 0x36
|
||||
SCM_TIMESTAMPING_PKTINFO = 0x3a
|
||||
SCM_TIMESTAMPNS = 0x23
|
||||
SCM_TS_OPT_ID = 0x51
|
||||
SCM_TXTIME = 0x3d
|
||||
SCM_WIFI_STATUS = 0x29
|
||||
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||
@@ -320,6 +347,9 @@ const (
|
||||
SO_CNX_ADVICE = 0x35
|
||||
SO_COOKIE = 0x39
|
||||
SO_DETACH_REUSEPORT_BPF = 0x44
|
||||
SO_DEVMEM_DMABUF = 0x4f
|
||||
SO_DEVMEM_DONTNEED = 0x50
|
||||
SO_DEVMEM_LINEAR = 0x4e
|
||||
SO_DOMAIN = 0x27
|
||||
SO_DONTROUTE = 0x5
|
||||
SO_ERROR = 0x4
|
||||
@@ -348,6 +378,7 @@ const (
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVPRIORITY = 0x52
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
|
||||
+34
@@ -78,6 +78,8 @@ const (
|
||||
ECHOPRT = 0x400
|
||||
EFD_CLOEXEC = 0x80000
|
||||
EFD_NONBLOCK = 0x800
|
||||
EPIOCGPARAMS = 0x80088a02
|
||||
EPIOCSPARAMS = 0x40088a01
|
||||
EPOLL_CLOEXEC = 0x80000
|
||||
ESR_MAGIC = 0x45535201
|
||||
EXTPROC = 0x10000
|
||||
@@ -87,6 +89,7 @@ const (
|
||||
FICLONE = 0x40049409
|
||||
FICLONERANGE = 0x4020940d
|
||||
FLUSHO = 0x1000
|
||||
FPMR_MAGIC = 0x46504d52
|
||||
FPSIMD_MAGIC = 0x46508001
|
||||
FS_IOC_ENABLE_VERITY = 0x40806685
|
||||
FS_IOC_GETFLAGS = 0x80086601
|
||||
@@ -106,15 +109,19 @@ const (
|
||||
F_SETOWN = 0x8
|
||||
F_UNLCK = 0x2
|
||||
F_WRLCK = 0x1
|
||||
GCS_MAGIC = 0x47435300
|
||||
HIDIOCGRAWINFO = 0x80084803
|
||||
HIDIOCGRDESC = 0x90044802
|
||||
HIDIOCGRDESCSIZE = 0x80044801
|
||||
HIDIOCREVOKE = 0x4004480d
|
||||
HUPCL = 0x400
|
||||
ICANON = 0x2
|
||||
IEXTEN = 0x8000
|
||||
IN_CLOEXEC = 0x80000
|
||||
IN_NONBLOCK = 0x800
|
||||
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
|
||||
IPV6_FLOWINFO_MASK = 0xffffff0f
|
||||
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
||||
ISIG = 0x1
|
||||
IUCLC = 0x200
|
||||
IXOFF = 0x1000
|
||||
@@ -151,9 +158,14 @@ const (
|
||||
NFDBITS = 0x40
|
||||
NLDLY = 0x100
|
||||
NOFLSH = 0x80
|
||||
NS_GET_MNTNS_ID = 0x8008b705
|
||||
NS_GET_NSTYPE = 0xb703
|
||||
NS_GET_OWNER_UID = 0xb704
|
||||
NS_GET_PARENT = 0xb702
|
||||
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||
NS_GET_USERNS = 0xb701
|
||||
OLCUC = 0x2
|
||||
ONLCR = 0x4
|
||||
@@ -197,6 +209,7 @@ const (
|
||||
PERF_EVENT_IOC_SET_BPF = 0x40042408
|
||||
PERF_EVENT_IOC_SET_FILTER = 0x40082406
|
||||
PERF_EVENT_IOC_SET_OUTPUT = 0x2405
|
||||
POE_MAGIC = 0x504f4530
|
||||
PPPIOCATTACH = 0x4004743d
|
||||
PPPIOCATTCHAN = 0x40047438
|
||||
PPPIOCBRIDGECHAN = 0x40047435
|
||||
@@ -232,6 +245,20 @@ const (
|
||||
PROT_BTI = 0x10
|
||||
PROT_MTE = 0x20
|
||||
PR_SET_PTRACER_ANY = 0xffffffffffffffff
|
||||
PTP_CLOCK_GETCAPS = 0x80503d01
|
||||
PTP_CLOCK_GETCAPS2 = 0x80503d0a
|
||||
PTP_ENABLE_PPS = 0x40043d04
|
||||
PTP_ENABLE_PPS2 = 0x40043d0d
|
||||
PTP_EXTTS_REQUEST = 0x40103d02
|
||||
PTP_EXTTS_REQUEST2 = 0x40103d0b
|
||||
PTP_MASK_CLEAR_ALL = 0x3d13
|
||||
PTP_MASK_EN_SINGLE = 0x40043d14
|
||||
PTP_PEROUT_REQUEST = 0x40383d03
|
||||
PTP_PEROUT_REQUEST2 = 0x40383d0c
|
||||
PTP_PIN_SETFUNC = 0x40603d07
|
||||
PTP_PIN_SETFUNC2 = 0x40603d10
|
||||
PTP_SYS_OFFSET = 0x43403d05
|
||||
PTP_SYS_OFFSET2 = 0x43403d0e
|
||||
PTRACE_PEEKMTETAGS = 0x21
|
||||
PTRACE_POKEMTETAGS = 0x22
|
||||
PTRACE_SYSEMU = 0x1f
|
||||
@@ -272,10 +299,13 @@ const (
|
||||
RTC_WIE_ON = 0x700f
|
||||
RTC_WKALM_RD = 0x80287010
|
||||
RTC_WKALM_SET = 0x4028700f
|
||||
SCM_DEVMEM_DMABUF = 0x4f
|
||||
SCM_DEVMEM_LINEAR = 0x4e
|
||||
SCM_TIMESTAMPING = 0x25
|
||||
SCM_TIMESTAMPING_OPT_STATS = 0x36
|
||||
SCM_TIMESTAMPING_PKTINFO = 0x3a
|
||||
SCM_TIMESTAMPNS = 0x23
|
||||
SCM_TS_OPT_ID = 0x51
|
||||
SCM_TXTIME = 0x3d
|
||||
SCM_WIFI_STATUS = 0x29
|
||||
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||
@@ -310,6 +340,9 @@ const (
|
||||
SO_CNX_ADVICE = 0x35
|
||||
SO_COOKIE = 0x39
|
||||
SO_DETACH_REUSEPORT_BPF = 0x44
|
||||
SO_DEVMEM_DMABUF = 0x4f
|
||||
SO_DEVMEM_DONTNEED = 0x50
|
||||
SO_DEVMEM_LINEAR = 0x4e
|
||||
SO_DOMAIN = 0x27
|
||||
SO_DONTROUTE = 0x5
|
||||
SO_ERROR = 0x4
|
||||
@@ -338,6 +371,7 @@ const (
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVPRIORITY = 0x52
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
|
||||
+31
@@ -78,6 +78,8 @@ const (
|
||||
ECHOPRT = 0x400
|
||||
EFD_CLOEXEC = 0x80000
|
||||
EFD_NONBLOCK = 0x800
|
||||
EPIOCGPARAMS = 0x80088a02
|
||||
EPIOCSPARAMS = 0x40088a01
|
||||
EPOLL_CLOEXEC = 0x80000
|
||||
EXTPROC = 0x10000
|
||||
FF1 = 0x8000
|
||||
@@ -107,12 +109,15 @@ const (
|
||||
HIDIOCGRAWINFO = 0x80084803
|
||||
HIDIOCGRDESC = 0x90044802
|
||||
HIDIOCGRDESCSIZE = 0x80044801
|
||||
HIDIOCREVOKE = 0x4004480d
|
||||
HUPCL = 0x400
|
||||
ICANON = 0x2
|
||||
IEXTEN = 0x8000
|
||||
IN_CLOEXEC = 0x80000
|
||||
IN_NONBLOCK = 0x800
|
||||
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
|
||||
IPV6_FLOWINFO_MASK = 0xffffff0f
|
||||
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
||||
ISIG = 0x1
|
||||
IUCLC = 0x200
|
||||
IXOFF = 0x1000
|
||||
@@ -152,9 +157,14 @@ const (
|
||||
NFDBITS = 0x40
|
||||
NLDLY = 0x100
|
||||
NOFLSH = 0x80
|
||||
NS_GET_MNTNS_ID = 0x8008b705
|
||||
NS_GET_NSTYPE = 0xb703
|
||||
NS_GET_OWNER_UID = 0xb704
|
||||
NS_GET_PARENT = 0xb702
|
||||
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||
NS_GET_USERNS = 0xb701
|
||||
OLCUC = 0x2
|
||||
ONLCR = 0x4
|
||||
@@ -231,6 +241,20 @@ const (
|
||||
PPPIOCUNBRIDGECHAN = 0x7434
|
||||
PPPIOCXFERUNIT = 0x744e
|
||||
PR_SET_PTRACER_ANY = 0xffffffffffffffff
|
||||
PTP_CLOCK_GETCAPS = 0x80503d01
|
||||
PTP_CLOCK_GETCAPS2 = 0x80503d0a
|
||||
PTP_ENABLE_PPS = 0x40043d04
|
||||
PTP_ENABLE_PPS2 = 0x40043d0d
|
||||
PTP_EXTTS_REQUEST = 0x40103d02
|
||||
PTP_EXTTS_REQUEST2 = 0x40103d0b
|
||||
PTP_MASK_CLEAR_ALL = 0x3d13
|
||||
PTP_MASK_EN_SINGLE = 0x40043d14
|
||||
PTP_PEROUT_REQUEST = 0x40383d03
|
||||
PTP_PEROUT_REQUEST2 = 0x40383d0c
|
||||
PTP_PIN_SETFUNC = 0x40603d07
|
||||
PTP_PIN_SETFUNC2 = 0x40603d10
|
||||
PTP_SYS_OFFSET = 0x43403d05
|
||||
PTP_SYS_OFFSET2 = 0x43403d0e
|
||||
PTRACE_SYSEMU = 0x1f
|
||||
PTRACE_SYSEMU_SINGLESTEP = 0x20
|
||||
RLIMIT_AS = 0x9
|
||||
@@ -269,10 +293,13 @@ const (
|
||||
RTC_WIE_ON = 0x700f
|
||||
RTC_WKALM_RD = 0x80287010
|
||||
RTC_WKALM_SET = 0x4028700f
|
||||
SCM_DEVMEM_DMABUF = 0x4f
|
||||
SCM_DEVMEM_LINEAR = 0x4e
|
||||
SCM_TIMESTAMPING = 0x25
|
||||
SCM_TIMESTAMPING_OPT_STATS = 0x36
|
||||
SCM_TIMESTAMPING_PKTINFO = 0x3a
|
||||
SCM_TIMESTAMPNS = 0x23
|
||||
SCM_TS_OPT_ID = 0x51
|
||||
SCM_TXTIME = 0x3d
|
||||
SCM_WIFI_STATUS = 0x29
|
||||
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
|
||||
@@ -307,6 +334,9 @@ const (
|
||||
SO_CNX_ADVICE = 0x35
|
||||
SO_COOKIE = 0x39
|
||||
SO_DETACH_REUSEPORT_BPF = 0x44
|
||||
SO_DEVMEM_DMABUF = 0x4f
|
||||
SO_DEVMEM_DONTNEED = 0x50
|
||||
SO_DEVMEM_LINEAR = 0x4e
|
||||
SO_DOMAIN = 0x27
|
||||
SO_DONTROUTE = 0x5
|
||||
SO_ERROR = 0x4
|
||||
@@ -335,6 +365,7 @@ const (
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVPRIORITY = 0x52
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
|
||||
+31
@@ -78,6 +78,8 @@ const (
|
||||
ECHOPRT = 0x400
|
||||
EFD_CLOEXEC = 0x80000
|
||||
EFD_NONBLOCK = 0x80
|
||||
EPIOCGPARAMS = 0x40088a02
|
||||
EPIOCSPARAMS = 0x80088a01
|
||||
EPOLL_CLOEXEC = 0x80000
|
||||
EXTPROC = 0x10000
|
||||
FF1 = 0x8000
|
||||
@@ -106,12 +108,15 @@ const (
|
||||
HIDIOCGRAWINFO = 0x40084803
|
||||
HIDIOCGRDESC = 0x50044802
|
||||
HIDIOCGRDESCSIZE = 0x40044801
|
||||
HIDIOCREVOKE = 0x8004480d
|
||||
HUPCL = 0x400
|
||||
ICANON = 0x2
|
||||
IEXTEN = 0x100
|
||||
IN_CLOEXEC = 0x80000
|
||||
IN_NONBLOCK = 0x80
|
||||
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
|
||||
IPV6_FLOWINFO_MASK = 0xfffffff
|
||||
IPV6_FLOWLABEL_MASK = 0xfffff
|
||||
ISIG = 0x1
|
||||
IUCLC = 0x200
|
||||
IXOFF = 0x1000
|
||||
@@ -148,9 +153,14 @@ const (
|
||||
NFDBITS = 0x20
|
||||
NLDLY = 0x100
|
||||
NOFLSH = 0x80
|
||||
NS_GET_MNTNS_ID = 0x4008b705
|
||||
NS_GET_NSTYPE = 0x2000b703
|
||||
NS_GET_OWNER_UID = 0x2000b704
|
||||
NS_GET_PARENT = 0x2000b702
|
||||
NS_GET_PID_FROM_PIDNS = 0x4004b706
|
||||
NS_GET_PID_IN_PIDNS = 0x4004b708
|
||||
NS_GET_TGID_FROM_PIDNS = 0x4004b707
|
||||
NS_GET_TGID_IN_PIDNS = 0x4004b709
|
||||
NS_GET_USERNS = 0x2000b701
|
||||
OLCUC = 0x2
|
||||
ONLCR = 0x4
|
||||
@@ -227,6 +237,20 @@ const (
|
||||
PPPIOCUNBRIDGECHAN = 0x20007434
|
||||
PPPIOCXFERUNIT = 0x2000744e
|
||||
PR_SET_PTRACER_ANY = 0xffffffff
|
||||
PTP_CLOCK_GETCAPS = 0x40503d01
|
||||
PTP_CLOCK_GETCAPS2 = 0x40503d0a
|
||||
PTP_ENABLE_PPS = 0x80043d04
|
||||
PTP_ENABLE_PPS2 = 0x80043d0d
|
||||
PTP_EXTTS_REQUEST = 0x80103d02
|
||||
PTP_EXTTS_REQUEST2 = 0x80103d0b
|
||||
PTP_MASK_CLEAR_ALL = 0x20003d13
|
||||
PTP_MASK_EN_SINGLE = 0x80043d14
|
||||
PTP_PEROUT_REQUEST = 0x80383d03
|
||||
PTP_PEROUT_REQUEST2 = 0x80383d0c
|
||||
PTP_PIN_SETFUNC = 0x80603d07
|
||||
PTP_PIN_SETFUNC2 = 0x80603d10
|
||||
PTP_SYS_OFFSET = 0x83403d05
|
||||
PTP_SYS_OFFSET2 = 0x83403d0e
|
||||
PTRACE_GETFPREGS = 0xe
|
||||
PTRACE_GET_THREAD_AREA = 0x19
|
||||
PTRACE_GET_THREAD_AREA_3264 = 0xc4
|
||||
@@ -275,10 +299,13 @@ const (
|
||||
RTC_WIE_ON = 0x2000700f
|
||||
RTC_WKALM_RD = 0x40287010
|
||||
RTC_WKALM_SET = 0x8028700f
|
||||
SCM_DEVMEM_DMABUF = 0x4f
|
||||
SCM_DEVMEM_LINEAR = 0x4e
|
||||
SCM_TIMESTAMPING = 0x25
|
||||
SCM_TIMESTAMPING_OPT_STATS = 0x36
|
||||
SCM_TIMESTAMPING_PKTINFO = 0x3a
|
||||
SCM_TIMESTAMPNS = 0x23
|
||||
SCM_TS_OPT_ID = 0x51
|
||||
SCM_TXTIME = 0x3d
|
||||
SCM_WIFI_STATUS = 0x29
|
||||
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
|
||||
@@ -313,6 +340,9 @@ const (
|
||||
SO_CNX_ADVICE = 0x35
|
||||
SO_COOKIE = 0x39
|
||||
SO_DETACH_REUSEPORT_BPF = 0x44
|
||||
SO_DEVMEM_DMABUF = 0x4f
|
||||
SO_DEVMEM_DONTNEED = 0x50
|
||||
SO_DEVMEM_LINEAR = 0x4e
|
||||
SO_DOMAIN = 0x1029
|
||||
SO_DONTROUTE = 0x10
|
||||
SO_ERROR = 0x1007
|
||||
@@ -341,6 +371,7 @@ const (
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x1004
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVPRIORITY = 0x52
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x1006
|
||||
|
||||
+31
@@ -78,6 +78,8 @@ const (
|
||||
ECHOPRT = 0x400
|
||||
EFD_CLOEXEC = 0x80000
|
||||
EFD_NONBLOCK = 0x80
|
||||
EPIOCGPARAMS = 0x40088a02
|
||||
EPIOCSPARAMS = 0x80088a01
|
||||
EPOLL_CLOEXEC = 0x80000
|
||||
EXTPROC = 0x10000
|
||||
FF1 = 0x8000
|
||||
@@ -106,12 +108,15 @@ const (
|
||||
HIDIOCGRAWINFO = 0x40084803
|
||||
HIDIOCGRDESC = 0x50044802
|
||||
HIDIOCGRDESCSIZE = 0x40044801
|
||||
HIDIOCREVOKE = 0x8004480d
|
||||
HUPCL = 0x400
|
||||
ICANON = 0x2
|
||||
IEXTEN = 0x100
|
||||
IN_CLOEXEC = 0x80000
|
||||
IN_NONBLOCK = 0x80
|
||||
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
|
||||
IPV6_FLOWINFO_MASK = 0xfffffff
|
||||
IPV6_FLOWLABEL_MASK = 0xfffff
|
||||
ISIG = 0x1
|
||||
IUCLC = 0x200
|
||||
IXOFF = 0x1000
|
||||
@@ -148,9 +153,14 @@ const (
|
||||
NFDBITS = 0x40
|
||||
NLDLY = 0x100
|
||||
NOFLSH = 0x80
|
||||
NS_GET_MNTNS_ID = 0x4008b705
|
||||
NS_GET_NSTYPE = 0x2000b703
|
||||
NS_GET_OWNER_UID = 0x2000b704
|
||||
NS_GET_PARENT = 0x2000b702
|
||||
NS_GET_PID_FROM_PIDNS = 0x4004b706
|
||||
NS_GET_PID_IN_PIDNS = 0x4004b708
|
||||
NS_GET_TGID_FROM_PIDNS = 0x4004b707
|
||||
NS_GET_TGID_IN_PIDNS = 0x4004b709
|
||||
NS_GET_USERNS = 0x2000b701
|
||||
OLCUC = 0x2
|
||||
ONLCR = 0x4
|
||||
@@ -227,6 +237,20 @@ const (
|
||||
PPPIOCUNBRIDGECHAN = 0x20007434
|
||||
PPPIOCXFERUNIT = 0x2000744e
|
||||
PR_SET_PTRACER_ANY = 0xffffffffffffffff
|
||||
PTP_CLOCK_GETCAPS = 0x40503d01
|
||||
PTP_CLOCK_GETCAPS2 = 0x40503d0a
|
||||
PTP_ENABLE_PPS = 0x80043d04
|
||||
PTP_ENABLE_PPS2 = 0x80043d0d
|
||||
PTP_EXTTS_REQUEST = 0x80103d02
|
||||
PTP_EXTTS_REQUEST2 = 0x80103d0b
|
||||
PTP_MASK_CLEAR_ALL = 0x20003d13
|
||||
PTP_MASK_EN_SINGLE = 0x80043d14
|
||||
PTP_PEROUT_REQUEST = 0x80383d03
|
||||
PTP_PEROUT_REQUEST2 = 0x80383d0c
|
||||
PTP_PIN_SETFUNC = 0x80603d07
|
||||
PTP_PIN_SETFUNC2 = 0x80603d10
|
||||
PTP_SYS_OFFSET = 0x83403d05
|
||||
PTP_SYS_OFFSET2 = 0x83403d0e
|
||||
PTRACE_GETFPREGS = 0xe
|
||||
PTRACE_GET_THREAD_AREA = 0x19
|
||||
PTRACE_GET_THREAD_AREA_3264 = 0xc4
|
||||
@@ -275,10 +299,13 @@ const (
|
||||
RTC_WIE_ON = 0x2000700f
|
||||
RTC_WKALM_RD = 0x40287010
|
||||
RTC_WKALM_SET = 0x8028700f
|
||||
SCM_DEVMEM_DMABUF = 0x4f
|
||||
SCM_DEVMEM_LINEAR = 0x4e
|
||||
SCM_TIMESTAMPING = 0x25
|
||||
SCM_TIMESTAMPING_OPT_STATS = 0x36
|
||||
SCM_TIMESTAMPING_PKTINFO = 0x3a
|
||||
SCM_TIMESTAMPNS = 0x23
|
||||
SCM_TS_OPT_ID = 0x51
|
||||
SCM_TXTIME = 0x3d
|
||||
SCM_WIFI_STATUS = 0x29
|
||||
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
|
||||
@@ -313,6 +340,9 @@ const (
|
||||
SO_CNX_ADVICE = 0x35
|
||||
SO_COOKIE = 0x39
|
||||
SO_DETACH_REUSEPORT_BPF = 0x44
|
||||
SO_DEVMEM_DMABUF = 0x4f
|
||||
SO_DEVMEM_DONTNEED = 0x50
|
||||
SO_DEVMEM_LINEAR = 0x4e
|
||||
SO_DOMAIN = 0x1029
|
||||
SO_DONTROUTE = 0x10
|
||||
SO_ERROR = 0x1007
|
||||
@@ -341,6 +371,7 @@ const (
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x1004
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVPRIORITY = 0x52
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x1006
|
||||
|
||||
Loaded 100 of 224 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user